home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Compilers⁄Interps / GCC-2.3.3r12 / Sources-CPlus / cp-lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-12  |  112.1 KB  |  4,231 lines  |  [TEXT/MPS ]

  1. /* Seperate lexical analyzer for GNU C++.
  2.    Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
  3.    Hacked by Michael Tiemann (tiemann@cygnus.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. /* This file is the lexical analyzer for GNU C++.  */
  23.  
  24. #if defined(GATHER_STATISTICS) || defined(SPEW_DEBUG)
  25. #undef YYDEBUG
  26. #define YYDEBUG 1
  27. #endif
  28.  
  29. #ifndef MPW
  30. #include <sys/types.h>
  31. #endif
  32. #include <stdio.h>
  33. #include <errno.h>
  34. #include <setjmp.h>
  35. #include "config.h"
  36. #include "input.h"
  37. #include "tree.h"
  38. #include "cp-lex.h"
  39. #include "cp-parse.h"
  40. #include "cp-tree.h"
  41. #include "flags.h"
  42. #include "obstack.h"
  43.  
  44. #ifdef MULTIBYTE_CHARS
  45. #ifndef MPW
  46. #include <stdlib.h>
  47. #endif
  48. #include <locale.h>
  49. #endif
  50.  
  51. #ifndef errno
  52. extern int errno;        /* needed for VAX.  */
  53. #endif
  54. extern jmp_buf toplevel;
  55.  
  56. #define obstack_chunk_alloc xmalloc
  57. #define obstack_chunk_free free
  58.  
  59. extern struct obstack *expression_obstack, permanent_obstack;
  60. extern struct obstack *current_obstack, *saveable_obstack;
  61.  
  62. extern double atof ();
  63.  
  64. extern char *get_directive_line ();    /* In c-common.c */
  65.  
  66. /* Given a file name X, return the nondirectory portion.
  67.    Keep in mind that X can be computed more than once.  */
  68. #ifndef FILE_NAME_NONDIRECTORY
  69. #define FILE_NAME_NONDIRECTORY(X)        \
  70.  (rindex (X, '/') != 0 ? rindex (X, '/') + 1 : X)
  71. #endif
  72.  
  73. extern char *index ();
  74. extern char *rindex ();
  75.  
  76. void extract_interface_info ();
  77. void yyerror ();
  78.  
  79. /* This obstack is needed to hold text.  It is not safe to use
  80.    TOKEN_BUFFER because `check_newline' calls `yylex'.  */
  81. static struct obstack inline_text_obstack;
  82. static char *inline_text_firstobj;
  83.  
  84. int end_of_file;
  85.  
  86. extern int first_token;
  87. extern struct obstack token_obstack;
  88.  
  89. /* ??? Don't really know where this goes yet.  */
  90. #if 1
  91. #include "cp-input.c"
  92. #else
  93. extern void put_back (/* int */);
  94. extern int input_redirected ();
  95. extern void feed_input (/* char *, int, struct obstack * */);
  96. #endif
  97.  
  98. /* Holds translations from TREE_CODEs to operator name strings,
  99.    i.e., opname_tab[PLUS_EXPR] == "+".  */
  100. char **opname_tab;
  101. char **assignop_tab;
  102.  
  103. extern int yychar;        /*  the lookahead symbol        */
  104. extern YYSTYPE yylval;        /*  the semantic value of the        */
  105.                 /*  lookahead symbol            */
  106.  
  107. #if 0
  108. YYLTYPE yylloc;            /*  location data for the lookahead    */
  109.                 /*  symbol                */
  110. #endif
  111.  
  112.  
  113. /* the declaration found for the last IDENTIFIER token read in.
  114.    yylex must look this up to detect typedefs, which get token type TYPENAME,
  115.    so it is left around in case the identifier is not a typedef but is
  116.    used in a context which makes it a reference to a variable.  */
  117. tree lastiddecl;
  118.  
  119. /* The elements of `ridpointers' are identifier nodes
  120.    for the reserved type names and storage classes.
  121.    It is indexed by a RID_... value.  */
  122. tree ridpointers[(int) RID_MAX];
  123.  
  124. /* We may keep statistics about how long which files took to compile.  */
  125. static int header_time, body_time;
  126. static tree get_time_identifier ();
  127. static tree filename_times;
  128. static tree this_filename_time;
  129.  
  130. /* For implementing #pragma unit.  */
  131. tree current_unit_name;
  132. tree current_unit_language;
  133.  
  134. /* Array for holding counts of the numbers of tokens seen.  */
  135. extern int *token_count;
  136.  
  137. /* Textual definition used for default functions.  */
  138. static char default_def[] = "{}";
  139.  
  140. /* Return something to represent absolute declarators containing a *.
  141.    TARGET is the absolute declarator that the * contains.
  142.    TYPE_QUALS is a list of modifiers such as const or volatile
  143.    to apply to the pointer type, represented as identifiers.
  144.  
  145.    We return an INDIRECT_REF whose "contents" are TARGET
  146.    and whose type is the modifier list.  */
  147.  
  148. tree
  149. make_pointer_declarator (type_quals, target)
  150.      tree type_quals, target;
  151. {
  152.   if (target && TREE_CODE (target) == IDENTIFIER_NODE
  153.       && ANON_AGGRNAME_P (target))
  154.     error ("type name expected before `*'");
  155.   target = build_parse_node (INDIRECT_REF, target);
  156.   TREE_TYPE (target) = type_quals;
  157.   return target;
  158. }
  159.  
  160. /* Return something to represent absolute declarators containing a &.
  161.    TARGET is the absolute declarator that the & contains.
  162.    TYPE_QUALS is a list of modifiers such as const or volatile
  163.    to apply to the reference type, represented as identifiers.
  164.  
  165.    We return an ADDR_EXPR whose "contents" are TARGET
  166.    and whose type is the modifier list.  */
  167.    
  168. tree
  169. make_reference_declarator (type_quals, target)
  170.      tree type_quals, target;
  171. {
  172.   if (target)
  173.     {
  174.       if (TREE_CODE (target) == ADDR_EXPR)
  175.     {
  176.       error ("cannot declare references to references");
  177.       return target;
  178.     }
  179.       if (TREE_CODE (target) == INDIRECT_REF)
  180.     {
  181.       error ("cannot declare pointers to references");
  182.       return target;
  183.     }
  184.       if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target))
  185.       error ("type name expected before `&'");
  186.     }
  187.   target = build_parse_node (ADDR_EXPR, target);
  188.   TREE_TYPE (target) = type_quals;
  189.   return target;
  190. }
  191.  
  192. /* Build names and nodes for overloaded operators.  */
  193.  
  194. tree ansi_opname[LAST_CPLUS_TREE_CODE];
  195. tree ansi_assopname[LAST_CPLUS_TREE_CODE];
  196.  
  197. char *
  198. operator_name_string (name)
  199.      tree name;
  200. {
  201.   char *opname = IDENTIFIER_POINTER (name) + 2;
  202.   tree *opname_table;
  203.   int i, assign;
  204.  
  205.   /* Works for builtin and user defined types.  */
  206.   if (IDENTIFIER_GLOBAL_VALUE (name)
  207.       && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL)
  208.     return IDENTIFIER_POINTER (name);
  209.  
  210.   if (opname[0] == 'a' && opname[2] != '\0')
  211.     {
  212.       opname += 1;
  213.       assign = 1;
  214.       opname_table = ansi_assopname;
  215.     }
  216.   else
  217.     {
  218.       assign = 0;
  219.       opname_table = ansi_opname;
  220.     }
  221.  
  222.   for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
  223.     {
  224.       if (opname[0] == IDENTIFIER_POINTER (opname_table[i])[2+assign]
  225.       && opname[1] == IDENTIFIER_POINTER (opname_table[i])[3+assign])
  226.     break;
  227.     }
  228.  
  229.   if (i == LAST_CPLUS_TREE_CODE)
  230.     return "<invalid operator>";
  231.  
  232.   if (assign)
  233.     return assignop_tab[i];
  234.   else
  235.     return opname_tab[i];
  236. }
  237.  
  238. int interface_only;        /* whether or not current file is only for
  239.                    interface definitions.  */
  240. int interface_unknown;        /* whether or not we know this class
  241.                    to behave according to #pragma interface.  */
  242.  
  243. /* lexical analyzer */
  244.  
  245. /* File used for outputting assembler code.  */
  246. extern FILE *asm_out_file;
  247.  
  248. #ifndef WCHAR_TYPE_SIZE
  249. #ifdef INT_TYPE_SIZE
  250. #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
  251. #else
  252. #define WCHAR_TYPE_SIZE    BITS_PER_WORD
  253. #endif
  254. #endif
  255.  
  256. /* Number of bytes in a wide character.  */
  257. #define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
  258.  
  259. static int maxtoken;        /* Current nominal length of token buffer.  */
  260. char *token_buffer;        /* Pointer to token buffer.
  261.                    Actual allocated length is maxtoken + 2.  */
  262.  
  263. #include "cp-hash.h"
  264.  
  265. int check_newline ();
  266.  
  267. /* Nonzero tells yylex to ignore \ in string constants.  */
  268. static int ignore_escape_flag = 0;
  269.  
  270. static int skip_white_space ();
  271.  
  272. static tree
  273. get_time_identifier (name)
  274.      char *name;
  275. {
  276.   tree time_identifier;
  277.   int len = strlen (name);
  278.   char *buf = (char *)alloca (len + 6);
  279.   strcpy (buf, "file ");
  280.   bcopy (name, buf+5, len);
  281.   buf[len+5] = '\0';
  282.   time_identifier = get_identifier (buf);
  283.   if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
  284.     {
  285.       push_obstacks_nochange ();
  286.       end_temporary_allocation ();
  287.       IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
  288.       IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
  289.       IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times;
  290.       filename_times = time_identifier;
  291.       pop_obstacks ();
  292.     }
  293.   return time_identifier;
  294. }
  295.  
  296. #ifdef __GNUC__
  297. __inline
  298. #endif
  299. static int
  300. my_get_run_time ()
  301. {
  302.   int old_quiet_flag = quiet_flag;
  303.   int this_time;
  304.   quiet_flag = 0;
  305.   this_time = get_run_time ();
  306.   quiet_flag = old_quiet_flag;
  307.   return this_time;
  308. }
  309.  
  310. /* Table indexed by tree code giving a string containing a character
  311.    classifying the tree code.  Possibilities are
  312.    t, d, s, c, r, <, 1 and 2.  See cp-tree.def for details.  */
  313.  
  314. #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
  315.  
  316. char *cplus_tree_code_type[] = {
  317.   "x",
  318. #include "cp-tree.def"
  319. };
  320. #undef DEFTREECODE
  321.  
  322. /* Table indexed by tree code giving number of expression
  323.    operands beyond the fixed part of the node structure.
  324.    Not used for types or decls.  */
  325.  
  326. #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
  327.  
  328. int cplus_tree_code_length[] = {
  329.   0,
  330. #include "cp-tree.def"
  331. };
  332. #undef DEFTREECODE
  333.  
  334. /* Names of tree components.
  335.    Used for printing out the tree and error messages.  */
  336. #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
  337.  
  338. char *cplus_tree_code_name[] = {
  339.   "@@dummy",
  340. #include "cp-tree.def"
  341. };
  342. #undef DEFTREECODE
  343.  
  344. /* toplev.c needs to call these.  */
  345.  
  346. void
  347. lang_init ()
  348. {
  349.   /* the beginning of the file is a new line; check for # */
  350.   /* With luck, we discover the real source file's name from that
  351.      and put it in input_filename.  */
  352.   put_back (check_newline ());
  353.  
  354.   if (flag_cadillac)
  355.     cadillac_start ();
  356.   if (flag_gnu_xref) GNU_xref_begin (input_filename);
  357. }
  358.  
  359. void
  360. lang_finish ()
  361. {
  362.   extern int errorcount, sorrycount;
  363.   if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);
  364. }
  365.  
  366. void
  367. init_filename_times ()
  368. {
  369.   this_filename_time = get_time_identifier ("<top level>");
  370.   if (flag_detailed_statistics)
  371.     {
  372.       header_time = 0;
  373.       body_time = my_get_run_time ();
  374.       TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
  375.     }
  376. }
  377.  
  378. /* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
  379.    Stuck this hack in to get the files open correctly; this is called
  380.    in place of init_lex if we are an unexec'd binary.    */
  381. void
  382. reinit_lang_specific ()
  383. {
  384.   init_filename_times ();
  385.   reinit_search_statistics ();
  386. }
  387.  
  388. void
  389. init_lex ()
  390. {
  391.   extern int *init_parse ();
  392.   extern char *(*decl_printable_name) ();
  393.   extern char *lang_printable_name ();
  394.  
  395.   int i;
  396.  
  397.   /* Initialize the lookahead machinery.  */
  398.   init_spew ();
  399.  
  400.   /* Make identifier nodes long enough for the language-specific slots.  */
  401.   set_identifier_size (sizeof (struct lang_identifier));
  402.   decl_printable_name = lang_printable_name;
  403.  
  404.   init_cplus_expand ();
  405.  
  406.   tree_code_type
  407.     = (char **) realloc (tree_code_type,
  408.              sizeof (char *) * LAST_CPLUS_TREE_CODE);
  409.   tree_code_length
  410.     = (int *) realloc (tree_code_length,
  411.                sizeof (int) * LAST_CPLUS_TREE_CODE);
  412.   tree_code_name
  413.     = (char **) realloc (tree_code_name,
  414.              sizeof (char *) * LAST_CPLUS_TREE_CODE);
  415.   bcopy ((char *)cplus_tree_code_type,
  416.      (char *)(tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE),
  417.      (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
  418.   bcopy ((char *)cplus_tree_code_length,
  419.      (char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE),
  420.      (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
  421.   bcopy ((char *)cplus_tree_code_name,
  422.      (char *)(tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE),
  423.      (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
  424.  
  425.   opname_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
  426.   bzero ((char *)opname_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
  427.   assignop_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
  428.   bzero ((char *)assignop_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
  429.  
  430.   ansi_opname[0] = get_identifier ("<invalid operator>");
  431.   for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
  432.     {
  433.       ansi_opname[i] = ansi_opname[0];
  434.       ansi_assopname[i] = ansi_opname[0];
  435.     }
  436.  
  437.   ansi_opname[(int) MULT_EXPR] = get_identifier ("__ml");
  438.   IDENTIFIER_OPNAME_P (ansi_opname[(int) MULT_EXPR]) = 1;
  439.   ansi_opname[(int) INDIRECT_REF] = ansi_opname[(int) MULT_EXPR];
  440.   ansi_assopname[(int) MULT_EXPR] = get_identifier ("__aml");
  441.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) MULT_EXPR]) = 1;
  442.   ansi_assopname[(int) INDIRECT_REF] = ansi_assopname[(int) MULT_EXPR];
  443.   ansi_opname[(int) TRUNC_MOD_EXPR] = get_identifier ("__md");
  444.   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUNC_MOD_EXPR]) = 1;
  445.   ansi_assopname[(int) TRUNC_MOD_EXPR] = get_identifier ("__amd");
  446.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) TRUNC_MOD_EXPR]) = 1;
  447.   ansi_opname[(int) CEIL_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
  448.   ansi_opname[(int) FLOOR_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
  449.   ansi_opname[(int) ROUND_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
  450.   ansi_opname[(int) MINUS_EXPR] = get_identifier ("__mi");
  451.   IDENTIFIER_OPNAME_P (ansi_opname[(int) MINUS_EXPR]) = 1;
  452.   ansi_opname[(int) NEGATE_EXPR] = ansi_opname[(int) MINUS_EXPR];
  453.   ansi_assopname[(int) MINUS_EXPR] = get_identifier ("__ami");
  454.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) MINUS_EXPR]) = 1;
  455.   ansi_assopname[(int) NEGATE_EXPR] = ansi_assopname[(int) MINUS_EXPR];
  456.   ansi_opname[(int) RSHIFT_EXPR] = get_identifier ("__rs");
  457.   IDENTIFIER_OPNAME_P (ansi_opname[(int) RSHIFT_EXPR]) = 1;
  458.   ansi_assopname[(int) RSHIFT_EXPR] = get_identifier ("__ars");
  459.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) RSHIFT_EXPR]) = 1;
  460.   ansi_opname[(int) NE_EXPR] = get_identifier ("__ne");
  461.   IDENTIFIER_OPNAME_P (ansi_opname[(int) NE_EXPR]) = 1;
  462.   ansi_opname[(int) GT_EXPR] = get_identifier ("__gt");
  463.   IDENTIFIER_OPNAME_P (ansi_opname[(int) GT_EXPR]) = 1;
  464.   ansi_opname[(int) GE_EXPR] = get_identifier ("__ge");
  465.   IDENTIFIER_OPNAME_P (ansi_opname[(int) GE_EXPR]) = 1;
  466.   ansi_opname[(int) BIT_IOR_EXPR] = get_identifier ("__or");
  467.   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_IOR_EXPR]) = 1;
  468.   ansi_assopname[(int) BIT_IOR_EXPR] = get_identifier ("__aor");
  469.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_IOR_EXPR]) = 1;
  470.   ansi_opname[(int) TRUTH_ANDIF_EXPR] = get_identifier ("__aa");
  471.   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ANDIF_EXPR]) = 1;
  472.   ansi_opname[(int) TRUTH_NOT_EXPR] = get_identifier ("__nt");
  473.   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_NOT_EXPR]) = 1;
  474.   ansi_opname[(int) PREINCREMENT_EXPR] = get_identifier ("__pp");
  475.   IDENTIFIER_OPNAME_P (ansi_opname[(int) PREINCREMENT_EXPR]) = 1;
  476.   ansi_opname[(int) POSTINCREMENT_EXPR] = ansi_opname[(int) PREINCREMENT_EXPR];
  477.   ansi_opname[(int) MODIFY_EXPR] = get_identifier ("__as");
  478.   IDENTIFIER_OPNAME_P (ansi_opname[(int) MODIFY_EXPR]) = 1;
  479.   ansi_assopname[(int) NOP_EXPR] = ansi_opname[(int) MODIFY_EXPR];
  480.   ansi_opname[(int) COMPOUND_EXPR] = get_identifier ("__cm");
  481.   IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPOUND_EXPR]) = 1;
  482.   ansi_opname[(int) EXACT_DIV_EXPR] = get_identifier ("__dv");
  483.   IDENTIFIER_OPNAME_P (ansi_opname[(int) EXACT_DIV_EXPR]) = 1;
  484.   ansi_assopname[(int) EXACT_DIV_EXPR] = get_identifier ("__adv");
  485.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) EXACT_DIV_EXPR]) = 1;
  486.   ansi_opname[(int) TRUNC_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
  487.   ansi_opname[(int) CEIL_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
  488.   ansi_opname[(int) FLOOR_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
  489.   ansi_opname[(int) ROUND_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
  490.   ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
  491.   ansi_assopname[(int) TRUNC_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
  492.   ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
  493.   ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
  494.   ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
  495.   ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
  496.   IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1;
  497.   ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl");
  498.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) PLUS_EXPR]) = 1;
  499.   ansi_opname[(int) CONVERT_EXPR] = ansi_opname[(int) PLUS_EXPR];
  500.   ansi_assopname[(int) CONVERT_EXPR] = ansi_assopname[(int) PLUS_EXPR];
  501.   ansi_opname[(int) LSHIFT_EXPR] = get_identifier ("__ls");
  502.   IDENTIFIER_OPNAME_P (ansi_opname[(int) LSHIFT_EXPR]) = 1;
  503.   ansi_assopname[(int) LSHIFT_EXPR] = get_identifier ("__als");
  504.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) LSHIFT_EXPR]) = 1;
  505.   ansi_opname[(int) EQ_EXPR] = get_identifier ("__eq");
  506.   IDENTIFIER_OPNAME_P (ansi_opname[(int) EQ_EXPR]) = 1;
  507.   ansi_opname[(int) LT_EXPR] = get_identifier ("__lt");
  508.   IDENTIFIER_OPNAME_P (ansi_opname[(int) LT_EXPR]) = 1;
  509.   ansi_opname[(int) LE_EXPR] = get_identifier ("__le");
  510.   IDENTIFIER_OPNAME_P (ansi_opname[(int) LE_EXPR]) = 1;
  511.   ansi_opname[(int) BIT_AND_EXPR] = get_identifier ("__ad");
  512.   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_AND_EXPR]) = 1;
  513.   ansi_assopname[(int) BIT_AND_EXPR] = get_identifier ("__aad");
  514.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_AND_EXPR]) = 1;
  515.   ansi_opname[(int) ADDR_EXPR] = ansi_opname[(int) BIT_AND_EXPR];
  516.   ansi_assopname[(int) ADDR_EXPR] = ansi_assopname[(int) BIT_AND_EXPR];
  517.   ansi_opname[(int) BIT_XOR_EXPR] = get_identifier ("__er");
  518.   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_XOR_EXPR]) = 1;
  519.   ansi_assopname[(int) BIT_XOR_EXPR] = get_identifier ("__aer");
  520.   IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_XOR_EXPR]) = 1;
  521.   ansi_opname[(int) TRUTH_ORIF_EXPR] = get_identifier ("__oo");
  522.   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ORIF_EXPR]) = 1;
  523.   ansi_opname[(int) BIT_NOT_EXPR] = get_identifier ("__co");
  524.   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_NOT_EXPR]) = 1;
  525.   ansi_opname[(int) PREDECREMENT_EXPR] = get_identifier ("__mm");
  526.   IDENTIFIER_OPNAME_P (ansi_opname[(int) PREDECREMENT_EXPR]) = 1;
  527.   ansi_opname[(int) POSTDECREMENT_EXPR] = ansi_opname[(int) PREDECREMENT_EXPR];
  528.   ansi_opname[(int) COMPONENT_REF] = get_identifier ("__rf");
  529.   IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPONENT_REF]) = 1;
  530.   ansi_opname[(int) MEMBER_REF] = get_identifier ("__rm");
  531.   IDENTIFIER_OPNAME_P (ansi_opname[(int) MEMBER_REF]) = 1;
  532.   ansi_opname[(int) CALL_EXPR] = get_identifier ("__cl");
  533.   IDENTIFIER_OPNAME_P (ansi_opname[(int) CALL_EXPR]) = 1;
  534.   ansi_opname[(int) ARRAY_REF] = get_identifier ("__vc");
  535.   IDENTIFIER_OPNAME_P (ansi_opname[(int) ARRAY_REF]) = 1;
  536.   ansi_opname[(int) NEW_EXPR] = get_identifier ("__nw");
  537.   IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1;
  538.   ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl");
  539.   IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1;
  540.   ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
  541.   IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
  542.  
  543.   /* This is not true: these operators are not defined in ANSI,
  544.      but we need them anyway.  */
  545.   ansi_opname[(int) MIN_EXPR] = get_identifier ("__mn");
  546.   IDENTIFIER_OPNAME_P (ansi_opname[(int) MIN_EXPR]) = 1;
  547.   ansi_opname[(int) MAX_EXPR] = get_identifier ("__mx");
  548.   IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
  549.   ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
  550.   IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
  551.   ansi_opname[(int) METHOD_CALL_EXPR] = get_identifier ("__wr");
  552.   IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1;
  553.  
  554.   init_method ();
  555.   gcc_obstack_init (&inline_text_obstack);
  556.   inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
  557.  
  558.   /* Start it at 0, because check_newline is called at the very beginning
  559.      and will increment it to 1.  */
  560.   lineno = 0;
  561.   current_function_decl = NULL;
  562.  
  563.   maxtoken = 40;
  564.   token_buffer = (char *) xmalloc (maxtoken + 2);
  565.  
  566.   ridpointers[(int) RID_INT] = get_identifier ("int");
  567.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
  568.               build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
  569.   ridpointers[(int) RID_CHAR] = get_identifier ("char");
  570.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
  571.               build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
  572.   ridpointers[(int) RID_VOID] = get_identifier ("void");
  573.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
  574.               build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
  575.   ridpointers[(int) RID_FLOAT] = get_identifier ("float");
  576.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
  577.               build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
  578.   ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
  579.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
  580.               build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
  581.   ridpointers[(int) RID_SHORT] = get_identifier ("short");
  582.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
  583.               build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
  584.   ridpointers[(int) RID_LONG] = get_identifier ("long");
  585.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
  586.               build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
  587.   ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
  588.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
  589.               build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
  590.   ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
  591.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
  592.               build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
  593.   ridpointers[(int) RID_INLINE] = get_identifier ("inline");
  594.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
  595.               build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
  596.   ridpointers[(int) RID_CONST] = get_identifier ("const");
  597.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
  598.               build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
  599.   ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
  600.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
  601.               build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
  602.   ridpointers[(int) RID_AUTO] = get_identifier ("auto");
  603.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
  604.               build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
  605.   ridpointers[(int) RID_STATIC] = get_identifier ("static");
  606.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
  607.               build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
  608.   ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
  609.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
  610.               build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
  611.   ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
  612.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
  613.               build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
  614.   ridpointers[(int) RID_REGISTER] = get_identifier ("register");
  615.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
  616.               build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
  617.  
  618.   /* C++ extensions. These are probably not correctly named. */
  619.   ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t");
  620.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR],
  621.               build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR]));
  622.   class_type_node = build_int_2 (class_type, 0);
  623.   TREE_TYPE (class_type_node) = class_type_node;
  624.   ridpointers[(int) RID_CLASS] = class_type_node;
  625.  
  626.   record_type_node = build_int_2 (record_type, 0);
  627.   TREE_TYPE (record_type_node) = record_type_node;
  628.   ridpointers[(int) RID_RECORD] = record_type_node;
  629.  
  630.   union_type_node = build_int_2 (union_type, 0);
  631.   TREE_TYPE (union_type_node) = union_type_node;
  632.   ridpointers[(int) RID_UNION] = union_type_node;
  633.  
  634.   enum_type_node = build_int_2 (enum_type, 0);
  635.   TREE_TYPE (enum_type_node) = enum_type_node;
  636.   ridpointers[(int) RID_ENUM] = enum_type_node;
  637.  
  638.   ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
  639.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
  640.               build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
  641.   ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
  642.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
  643.               build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
  644.  
  645.   ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
  646.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
  647.               build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
  648.   ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
  649.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
  650.               build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
  651.   ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
  652.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
  653.               build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
  654.  
  655.   if (flag_apple)
  656.     {
  657.       /* Add Apple-defined keywords to the table. */
  658.       ridpointers[(int) RID_COMP] = get_identifier ("comp"); 
  659.       ridpointers[(int) RID_EXTENDED] = get_identifier ("extended");
  660.       ridpointers[(int) RID_PASCAL] = get_identifier ("pascal");
  661.     }
  662.  
  663.   /* Exception handling extensions.  */
  664.   exception_type_node = build_int_2 (exception_type, 0);
  665.   TREE_TYPE (exception_type_node) = exception_type_node;
  666.   ridpointers[(int) RID_EXCEPTION] = exception_type_node;
  667.  
  668.   opname_tab[(int) COMPONENT_REF] = "->";
  669.   opname_tab[(int) MEMBER_REF] = "->*";
  670.   opname_tab[(int) METHOD_CALL_EXPR] = "->()";
  671.   opname_tab[(int) INDIRECT_REF] = "(unary *)";
  672.   opname_tab[(int) ARRAY_REF] = "[]";
  673.   opname_tab[(int) MODIFY_EXPR] = "=";
  674.   opname_tab[(int) NEW_EXPR] = "new";
  675.   opname_tab[(int) DELETE_EXPR] = "delete";
  676.   opname_tab[(int) COND_EXPR] = "... ? ... : ...";
  677.   opname_tab[(int) CALL_EXPR] = "()";
  678.   opname_tab[(int) PLUS_EXPR] = "+";
  679.   opname_tab[(int) MINUS_EXPR] = "-";
  680.   opname_tab[(int) MULT_EXPR] = "*";
  681.   opname_tab[(int) TRUNC_DIV_EXPR] = "/";
  682.   opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
  683.   opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
  684.   opname_tab[(int) ROUND_DIV_EXPR] = "(round /)";
  685.   opname_tab[(int) TRUNC_MOD_EXPR] = "%";
  686.   opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)";
  687.   opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)";
  688.   opname_tab[(int) ROUND_MOD_EXPR] = "(round %)";
  689.   opname_tab[(int) NEGATE_EXPR] = "-";
  690.   opname_tab[(int) MIN_EXPR] = "<?";
  691.   opname_tab[(int) MAX_EXPR] = ">?";
  692.   opname_tab[(int) ABS_EXPR] = "abs";
  693.   opname_tab[(int) FFS_EXPR] = "ffs";
  694.   opname_tab[(int) LSHIFT_EXPR] = "<<";
  695.   opname_tab[(int) RSHIFT_EXPR] = ">>";
  696.   opname_tab[(int) BIT_IOR_EXPR] = "|";
  697.   opname_tab[(int) BIT_XOR_EXPR] = "^";
  698.   opname_tab[(int) BIT_AND_EXPR] = "&";
  699.   opname_tab[(int) BIT_ANDTC_EXPR] = "&~";
  700.   opname_tab[(int) BIT_NOT_EXPR] = "~";
  701.   opname_tab[(int) TRUTH_ANDIF_EXPR] = "&&";
  702.   opname_tab[(int) TRUTH_ORIF_EXPR] = "||";
  703.   opname_tab[(int) TRUTH_AND_EXPR] = "strict &&";
  704.   opname_tab[(int) TRUTH_OR_EXPR] = "strict ||";
  705.   opname_tab[(int) TRUTH_NOT_EXPR] = "!";
  706.   opname_tab[(int) LT_EXPR] = "<";
  707.   opname_tab[(int) LE_EXPR] = "<=";
  708.   opname_tab[(int) GT_EXPR] = ">";
  709.   opname_tab[(int) GE_EXPR] = ">=";
  710.   opname_tab[(int) EQ_EXPR] = "==";
  711.   opname_tab[(int) NE_EXPR] = "!=";
  712.   opname_tab[(int) IN_EXPR] = "in";
  713.   opname_tab[(int) SET_LE_EXPR] = "subset";
  714.   opname_tab[(int) CARD_EXPR] = "#";
  715.   opname_tab[(int) RANGE_EXPR] = "..";
  716.   opname_tab[(int) CONVERT_EXPR] = "(unary +)";
  717.   opname_tab[(int) ADDR_EXPR] = "(unary &)";
  718.   opname_tab[(int) PREDECREMENT_EXPR] = "--";
  719.   opname_tab[(int) PREINCREMENT_EXPR] = "++";
  720.   opname_tab[(int) POSTDECREMENT_EXPR] = "--";
  721.   opname_tab[(int) POSTINCREMENT_EXPR] = "++";
  722.   opname_tab[(int) COMPOUND_EXPR] = ",";
  723.  
  724.   assignop_tab[(int) NOP_EXPR] = "=";
  725.   assignop_tab[(int) PLUS_EXPR] =  "+=";
  726.   assignop_tab[(int) CONVERT_EXPR] =  "+=";
  727.   assignop_tab[(int) MINUS_EXPR] = "-=";
  728.   assignop_tab[(int) NEGATE_EXPR] = "-=";
  729.   assignop_tab[(int) MULT_EXPR] = "*=";
  730.   assignop_tab[(int) INDIRECT_REF] = "*=";
  731.   assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
  732.   assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)";
  733.   assignop_tab[(int) CEIL_DIV_EXPR] = "(ceiling /=)";
  734.   assignop_tab[(int) FLOOR_DIV_EXPR] = "(floor /=)";
  735.   assignop_tab[(int) ROUND_DIV_EXPR] = "(round /=)";
  736.   assignop_tab[(int) TRUNC_MOD_EXPR] = "%=";
  737.   assignop_tab[(int) CEIL_MOD_EXPR] = "(ceiling %=)";
  738.   assignop_tab[(int) FLOOR_MOD_EXPR] = "(floor %=)";
  739.   assignop_tab[(int) ROUND_MOD_EXPR] = "(round %=)";
  740.   assignop_tab[(int) MIN_EXPR] = "<?=";
  741.   assignop_tab[(int) MAX_EXPR] = ">?=";
  742.   assignop_tab[(int) LSHIFT_EXPR] = "<<=";
  743.   assignop_tab[(int) RSHIFT_EXPR] = ">>=";
  744.   assignop_tab[(int) BIT_IOR_EXPR] = "|=";
  745.   assignop_tab[(int) BIT_XOR_EXPR] = "^=";
  746.   assignop_tab[(int) BIT_AND_EXPR] = "&=";
  747.   assignop_tab[(int) ADDR_EXPR] = "&=";
  748.  
  749.   init_filename_times ();
  750.  
  751. #define UNSET_RESERVED_WORD(STRING) \
  752.   do { is_reserved_word (STRING, sizeof (STRING) - 1)->name = ""; } while (0)
  753.  
  754.   if (flag_ansi_exceptions)
  755.       flag_handle_exceptions = 2;
  756.  
  757.   if (!flag_ansi_exceptions)
  758.     {
  759.       UNSET_RESERVED_WORD ("catch");
  760.     }
  761.  
  762.   if (! flag_handle_exceptions)
  763.     {
  764.       /* Easiest way to not recognize exception
  765.      handling extensions...  */
  766.       UNSET_RESERVED_WORD ("all");
  767.       UNSET_RESERVED_WORD ("except");
  768.       UNSET_RESERVED_WORD ("exception");
  769.       UNSET_RESERVED_WORD ("raise");
  770.       UNSET_RESERVED_WORD ("raises");
  771.       UNSET_RESERVED_WORD ("reraise");
  772.       UNSET_RESERVED_WORD ("try");
  773.       UNSET_RESERVED_WORD ("throw");
  774.     }
  775.   else if (flag_ansi_exceptions)
  776.     {
  777.       /* Easiest way to not recognize exception
  778.      handling extensions...  */
  779.       UNSET_RESERVED_WORD ("exception");
  780.       UNSET_RESERVED_WORD ("all");
  781.       UNSET_RESERVED_WORD ("except");
  782.       UNSET_RESERVED_WORD ("raise");
  783.       UNSET_RESERVED_WORD ("raises");
  784.       UNSET_RESERVED_WORD ("reraise");
  785.       is_reserved_word ("try", sizeof ("try") - 1)->token = ANSI_TRY;
  786.       is_reserved_word ("throw", sizeof ("throw") - 1)->token = ANSI_THROW;
  787.     }
  788.   if (! (flag_gc || flag_dossier))
  789.     {
  790.       UNSET_RESERVED_WORD ("classof");
  791.       UNSET_RESERVED_WORD ("headof");
  792.     }
  793.   if (flag_no_asm)
  794.     UNSET_RESERVED_WORD ("asm");
  795.   if (flag_no_asm || flag_traditional)
  796.     UNSET_RESERVED_WORD ("typeof");
  797. #ifndef SOS
  798.   UNSET_RESERVED_WORD ("dynamic");
  799. #endif
  800.  
  801.   token_count = init_parse ();
  802.   interface_unknown = 1;
  803. }
  804.  
  805. void
  806. reinit_parse_for_function ()
  807. {
  808.   current_base_init_list = NULL_TREE;
  809.   current_member_init_list = NULL_TREE;
  810. }
  811.  
  812. static
  813. #ifdef __GNUC__
  814. __inline
  815. #endif
  816. void
  817. yyprint (file, yychar, yylval)
  818.      FILE *file;
  819.      int yychar;
  820.      YYSTYPE yylval;
  821. {
  822.   tree t;
  823.   switch (yychar)
  824.     {
  825.     case IDENTIFIER:
  826.     case TYPENAME:
  827.     case TYPESPEC:
  828.     case PTYPENAME:
  829.     case IDENTIFIER_DEFN:
  830.     case TYPENAME_DEFN:
  831.     case PTYPENAME_DEFN:
  832.     case TYPENAME_COLON:
  833.     case TYPENAME_ELLIPSIS:
  834.     case SCOPED_TYPENAME:
  835.     case SCSPEC:
  836.       t = yylval.ttype;
  837.     print_id:
  838.       my_friendly_assert (TREE_CODE (t) == IDENTIFIER_NODE, 224);
  839.       if (IDENTIFIER_POINTER (t))
  840.       fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
  841.       break;
  842.     case AGGR:
  843.       if (yylval.ttype == class_type_node)
  844.     fprintf (file, " `class'");
  845.       else if (yylval.ttype == record_type_node)
  846.     fprintf (file, " `struct'");
  847.       else if (yylval.ttype == union_type_node)
  848.     fprintf (file, " `union'");
  849.       else if (yylval.ttype == enum_type_node)
  850.     fprintf (file, " `enum'");
  851.       else
  852.     my_friendly_abort (80);
  853.       break;
  854.     case PRE_PARSED_CLASS_DECL:
  855.       t = yylval.ttype;
  856.       my_friendly_assert (TREE_CODE (t) == TREE_LIST, 225);
  857.       t = TREE_VALUE (t);
  858.       goto print_id;
  859.     }
  860. }
  861.  
  862. static int *reduce_count;
  863. int *token_count;
  864.  
  865. #define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
  866. #define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
  867.  
  868. int *
  869. init_parse ()
  870. {
  871. #ifdef GATHER_STATISTICS
  872.   reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
  873.   bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
  874.   reduce_count += 1;
  875.   token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1));
  876.   bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
  877.   token_count += 1;
  878. #endif
  879.   return token_count;
  880. }
  881.  
  882. #ifdef GATHER_STATISTICS
  883. void
  884. yyhook (yyn)
  885.      int yyn;
  886. {
  887.   reduce_count[yyn] += 1;
  888. }
  889. #endif
  890.  
  891. static int
  892. reduce_cmp (p, q)
  893.      int *p, *q;
  894. {
  895.   return reduce_count[*q] - reduce_count[*p];
  896. }
  897.  
  898. static int
  899. token_cmp (p, q)
  900.      int *p, *q;
  901. {
  902.   return token_count[*q] - token_count[*p];
  903. }
  904.  
  905. void
  906. print_parse_statistics ()
  907. {
  908. #ifdef GATHER_STATISTICS
  909. #if YYDEBUG != 0
  910.   int i;
  911.   int maxlen = REDUCE_LENGTH;
  912.   unsigned *sorted;
  913.   
  914.   if (reduce_count[-1] == 0)
  915.     return;
  916.  
  917.   if (TOKEN_LENGTH > REDUCE_LENGTH)
  918.     maxlen = TOKEN_LENGTH;
  919.   sorted = (unsigned *) alloca (sizeof (int) * maxlen);
  920.  
  921.   for (i = 0; i < TOKEN_LENGTH; i++)
  922.     sorted[i] = i;
  923.   qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp);
  924.   for (i = 0; i < TOKEN_LENGTH; i++)
  925.     {
  926.       int index = sorted[i];
  927.       if (token_count[index] == 0)
  928.     break;
  929.       if (token_count[index] < token_count[-1])
  930.     break;
  931.       fprintf (stderr, "token %d, `%s', count = %d\n",
  932.            index, yytname[YYTRANSLATE (index)], token_count[index]);
  933.     }
  934.   fprintf (stderr, "\n");
  935.   for (i = 0; i < REDUCE_LENGTH; i++)
  936.     sorted[i] = i;
  937.   qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp);
  938.   for (i = 0; i < REDUCE_LENGTH; i++)
  939.     {
  940.       int index = sorted[i];
  941.       if (reduce_count[index] == 0)
  942.     break;
  943.       if (reduce_count[index] < reduce_count[-1])
  944.     break;
  945.       fprintf (stderr, "rule %d, line %d, count = %d\n",
  946.            index, yyrline[index], reduce_count[index]);
  947.     }
  948.   fprintf (stderr, "\n");
  949. #endif
  950. #endif
  951. }
  952.  
  953. /* Sets the value of the 'yydebug' variable to VALUE.
  954.    This is a function so we don't have to have YYDEBUG defined
  955.    in order to build the compiler.  */
  956. void
  957. set_yydebug (value)
  958.      int value;
  959. {
  960. #if YYDEBUG != 0
  961.   yydebug = value;
  962. #else
  963.   warning ("YYDEBUG not defined.");
  964. #endif
  965. }
  966.  
  967. #ifdef SPEW_DEBUG
  968. const char *
  969. debug_yytranslate (value)
  970.     int value;
  971. {
  972.   return yytname[YYTRANSLATE (value)];
  973. }
  974.  
  975. #endif
  976.  
  977. /* Functions and data structures for #pragma interface.
  978.  
  979.    `#pragma implementation' means that the main file being compiled
  980.    is considered to implement (provide) the classes that appear in
  981.    its main body.  I.e., if this is file "foo.cc", and class `bar'
  982.    is defined in "foo.cc", then we say that "foo.cc implements bar".
  983.  
  984.    All main input files "implement" themselves automagically.
  985.  
  986.    `#pragma interface' means that unless this file (of the form "foo.h"
  987.    is not presently being included by file "foo.cc", the
  988.    CLASSTYPE_INTERFACE_ONLY bit gets set.  The effect is that none
  989.    of the vtables nor any of the inline functions defined in foo.h
  990.    will ever be output.
  991.  
  992.    There are cases when we want to link files such as "defs.h" and
  993.    "main.cc".  In this case, we give "defs.h" a `#pragma interface',
  994.    and "main.cc" has `#pragma implementation "defs.h"'.  */
  995.  
  996. struct impl_files
  997. {
  998.   char *filename;
  999.   struct impl_files *next;
  1000. };
  1001.  
  1002. static struct impl_files *impl_file_chain;
  1003.  
  1004. /* Helper function to load global variables with interface
  1005.    information.  */
  1006. void
  1007. extract_interface_info ()
  1008. {
  1009.   tree fileinfo = get_time_identifier (input_filename);
  1010.   fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
  1011.   interface_only = TREE_INT_CST_LOW (fileinfo);
  1012.   interface_unknown = TREE_INT_CST_HIGH (fileinfo);
  1013. }
  1014.  
  1015. /* Return nonzero if S and T are not considered part of an
  1016.    INTERFACE/IMPLEMENTATION pair.  Otherwise, return 0.  */
  1017. static int
  1018. interface_strcmp (s)
  1019.      char *s;
  1020. {
  1021.   /* Set the interface/implementation bits for this scope.  */
  1022.   struct impl_files *ifiles;
  1023.   char *s1;
  1024.  
  1025.   s = FILE_NAME_NONDIRECTORY (s);
  1026.  
  1027.   for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
  1028.     {
  1029.       char *t1 = ifiles->filename;
  1030.       s1 = s;
  1031.  
  1032.       if (*s1 != *t1 || *s1 == 0)
  1033.     continue;
  1034.  
  1035.       while (*s1 == *t1 && *s1 != 0)
  1036.     s1++, t1++;
  1037.  
  1038.       /* A match.  */
  1039.       if (*s1 == *t1)
  1040.     return 0;
  1041.  
  1042.       /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc.  */
  1043.       if (index (s1, '.') || index (t1, '.'))
  1044.     continue;
  1045.  
  1046.       if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.')
  1047.     continue;
  1048.  
  1049.       /* A match.  */
  1050.       return 0;
  1051.     }
  1052.  
  1053.   /* No matches.  */
  1054.   return 1;
  1055. }
  1056.  
  1057. void
  1058. set_typedecl_interface_info (prev, vars)
  1059.      tree prev, vars;
  1060. {
  1061.   tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
  1062.   tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
  1063.   tree type = TREE_TYPE (vars);
  1064.  
  1065.   CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
  1066.     = interface_strcmp (DECL_SOURCE_FILE (vars));
  1067. }
  1068.  
  1069. void
  1070. set_vardecl_interface_info (prev, vars)
  1071.      tree prev, vars;
  1072. {
  1073.   tree type = DECL_CONTEXT (vars);
  1074.  
  1075.   if (CLASSTYPE_INTERFACE_UNKNOWN (type) == 0)
  1076.     {
  1077.       if (CLASSTYPE_INTERFACE_ONLY (type))
  1078.     set_typedecl_interface_info (prev, TYPE_NAME (type));
  1079.       else
  1080.     CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
  1081.       DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
  1082.       TREE_PUBLIC (vars) = 1;
  1083.     }
  1084. }
  1085.  
  1086. /* Called from the top level: if there are any pending inlines to
  1087.    do, set up to process them now.  */
  1088. void
  1089. do_pending_inlines ()
  1090. {
  1091.   struct pending_inline *prev = 0, *tail;
  1092.   struct pending_inline *t;
  1093.  
  1094.   /* Reverse the pending inline functions, since
  1095.      they were cons'd instead of appended.  */
  1096.   
  1097.   for (t = pending_inlines; t; t = tail)
  1098.     {
  1099.       t->deja_vu = 1;
  1100.       tail = t->next;
  1101.       t->next = prev;
  1102.       prev = t;
  1103.     }
  1104.   /* Reset to zero so that if the inline functions we are currently
  1105.      processing define inline functions of their own, that is handled
  1106.      correctly.  ??? This hasn't been checked in a while.  */
  1107.   pending_inlines = 0;
  1108.   
  1109.   /* Now start processing the first inline function.  */
  1110.   t = prev;
  1111.   my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
  1112.               226);
  1113.   if (t->parm_vec)
  1114.     push_template_decls (t->parm_vec, t->bindings, 0);
  1115.   if (t->len > 0)
  1116.     {
  1117.       feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0);
  1118.       lineno = t->lineno;
  1119. #if 0
  1120.       if (input_filename != t->filename)
  1121.     {
  1122.       input_filename = t->filename;
  1123.       /* Get interface/implementation back in sync.  */
  1124.       extract_interface_info ();
  1125.     }
  1126. #else
  1127.       input_filename = t->filename;
  1128.       interface_unknown = t->interface == 1;
  1129.       interface_only = t->interface == 0;
  1130. #endif
  1131.       yychar = PRE_PARSED_FUNCTION_DECL;
  1132.     }
  1133.   /* Pass back a handle on the rest of the inline functions, so that they
  1134.      can be processed later.  */
  1135.   yylval.ttype = build_tree_list ((tree) t, t->fndecl);
  1136.   if (flag_default_inline && t->fndecl
  1137.       /* If we're working from a template, don't change
  1138.      the `inline' state.  */
  1139.       && t->parm_vec == NULL_TREE)
  1140.     DECL_INLINE (t->fndecl) = 1;
  1141.   DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
  1142. }
  1143.  
  1144. extern struct pending_input *to_be_restored;
  1145. static int nextchar = -1;
  1146.  
  1147. void
  1148. process_next_inline (t)
  1149.      tree t;
  1150. {
  1151.   struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
  1152.   my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
  1153.               227);
  1154.   if (i->parm_vec)
  1155.     pop_template_decls (i->parm_vec, i->bindings, 0);
  1156.   i = i->next;
  1157.   if (yychar == YYEMPTY)
  1158.     yychar = yylex ();
  1159.   if (yychar != END_OF_SAVED_INPUT)
  1160.     {
  1161.       error ("parse error at end of saved function text");
  1162.       /* restore_pending_input will abort unless yychar is either
  1163.        * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
  1164.        * hosed, feed back YYEMPTY.
  1165.        *  We also need to discard nextchar, since that may have gotten
  1166.        * set as well.
  1167.        */
  1168.       nextchar = -1;
  1169.     }
  1170.   yychar = YYEMPTY;
  1171.   if (to_be_restored == 0)
  1172.     my_friendly_abort (123);
  1173.   restore_pending_input (to_be_restored);
  1174.   to_be_restored = 0;
  1175.   if (i && i->fndecl != NULL_TREE)
  1176.     {
  1177.       my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
  1178.               228);
  1179.       if (i->parm_vec)
  1180.     push_template_decls (i->parm_vec, i->bindings, 0);
  1181.       feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0);
  1182.       lineno = i->lineno;
  1183.       input_filename = i->filename;
  1184.       yychar = PRE_PARSED_FUNCTION_DECL;
  1185.       yylval.ttype = build_tree_list ((tree) i, i->fndecl);
  1186.       if (flag_default_inline
  1187.       /* If we're working from a template, don't change
  1188.          the `inline' state.  */
  1189.       && i->parm_vec == NULL_TREE)
  1190.     DECL_INLINE (i->fndecl) = 1;
  1191.       DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
  1192.     }
  1193.   if (i)
  1194.     {
  1195.       interface_unknown = i->interface == 1;
  1196.       interface_only = i->interface == 0;
  1197.     }
  1198.   else
  1199.     extract_interface_info ();
  1200. }
  1201.  
  1202. /* Since inline methods can refer to text which has not yet been seen,
  1203.    we store the text of the method in a structure which is placed in the
  1204.    DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
  1205.    After parsing the body of the class definition, the FUNCTION_DECL's are
  1206.    scanned to see which ones have this field set.  Those are then digested
  1207.    one at a time.
  1208.  
  1209.    This function's FUNCTION_DECL will have a bit set in its common so
  1210.    that we know to watch out for it.  */
  1211.  
  1212. void
  1213. consume_string (this_obstack)
  1214.      register struct obstack *this_obstack;
  1215. {
  1216.   register char c;
  1217.   do
  1218.     {
  1219.       c = getch ();
  1220.       if (c == '\\')
  1221.     {
  1222.       obstack_1grow (this_obstack, c);
  1223.       c = getch ();
  1224.       obstack_1grow (this_obstack, c);
  1225.       continue;
  1226.     }
  1227.       if (c == '\n')
  1228.     {
  1229.       if (pedantic)
  1230.         pedwarn ("ANSI C++ forbids newline in string constant");
  1231.       lineno++;
  1232.     }
  1233.       obstack_1grow (this_obstack, c);
  1234.     }
  1235.   while (c != '\"');
  1236. }
  1237.  
  1238. static int nextyychar = YYEMPTY;
  1239. static YYSTYPE nextyylval;
  1240.  
  1241. struct pending_input {
  1242.   int nextchar, yychar, nextyychar, eof;
  1243.   YYSTYPE yylval, nextyylval;
  1244.   struct obstack token_obstack;
  1245.   int first_token;
  1246. };
  1247.  
  1248. struct pending_input *
  1249. save_pending_input ()
  1250. {
  1251.   struct pending_input *p;
  1252.   p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
  1253.   p->nextchar = nextchar;
  1254.   p->yychar = yychar;
  1255.   p->nextyychar = nextyychar;
  1256.   p->yylval = yylval;
  1257.   p->nextyylval = nextyylval;
  1258.   p->eof = end_of_file;
  1259.   yychar = nextyychar = YYEMPTY;
  1260.   nextchar = -1;
  1261.   p->first_token = first_token;
  1262.   p->token_obstack = token_obstack;
  1263.  
  1264.   first_token = 0;
  1265.   gcc_obstack_init (&token_obstack);
  1266.   end_of_file = 0;
  1267.   return p;
  1268. }
  1269.  
  1270. void
  1271. restore_pending_input (p)
  1272.      struct pending_input *p;
  1273. {
  1274.   my_friendly_assert (nextchar == -1, 229);
  1275.   nextchar = p->nextchar;
  1276.   my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230);
  1277.   yychar = p->yychar;
  1278.   my_friendly_assert (nextyychar == YYEMPTY, 231);
  1279.   nextyychar = p->nextyychar;
  1280.   yylval = p->yylval;
  1281.   nextyylval = p->nextyylval;
  1282.   first_token = p->first_token;
  1283.   obstack_free (&token_obstack, (char *) 0);
  1284.   token_obstack = p->token_obstack;
  1285.   end_of_file = p->eof;
  1286.   free (p);
  1287. }
  1288.  
  1289. /* Return next non-whitespace input character, which may come
  1290.    from `finput', or from `nextchar'.  */
  1291. static int
  1292. yynextch ()
  1293. {
  1294.   int c;
  1295.  
  1296.   if (nextchar >= 0)
  1297.     {
  1298.       c = nextchar;
  1299.       nextchar = -1;
  1300.     }
  1301.   else c = getch ();
  1302.   return skip_white_space (c);
  1303. }
  1304.  
  1305. /* Unget character CH from the input stream.
  1306.    If RESCAN is non-zero, then we want to `see' this
  1307.    character as the next input token.  */
  1308. void
  1309. yyungetc (ch, rescan)
  1310.      int ch;
  1311.      int rescan;
  1312. {
  1313.   /* Unget a character from the input stream.  */
  1314.   if (yychar == YYEMPTY || rescan == 0)
  1315.     {
  1316.       if (nextchar >= 0)
  1317.     put_back (nextchar);
  1318.       nextchar = ch;
  1319.     }
  1320.   else
  1321.     {
  1322.       my_friendly_assert (nextyychar == YYEMPTY, 232);
  1323.       nextyychar = yychar;
  1324.       nextyylval = yylval;
  1325.       yychar = ch;
  1326.     }
  1327. }
  1328.  
  1329. /* This function stores away the text for an inline function that should
  1330.    be processed later.  It decides how much later, and may need to move
  1331.    the info between obstacks; therefore, the caller should not refer to
  1332.    the T parameter after calling this function.
  1333.  
  1334.    This function also stores the list of template-parameter bindings that
  1335.    will be needed for expanding the template, if any.  */
  1336.  
  1337. static void
  1338. store_pending_inline (decl, t)
  1339.      tree decl;
  1340.      struct pending_inline *t;
  1341. {
  1342.   extern int processing_template_defn;
  1343.   int delay_to_eof = 0;
  1344.   struct pending_inline **inlines;
  1345.  
  1346.   t->fndecl = decl;
  1347.   /* Default: compile right away, and no extra bindings are needed.  */
  1348.   t->parm_vec = t->bindings = 0;
  1349.   if (processing_template_defn)
  1350.     {
  1351.       tree type = current_class_type;
  1352.       /* Assumption: In this (possibly) nested class sequence, only
  1353.      one name will have template parms.  */
  1354.       while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't')
  1355.     {
  1356.       tree decl = TYPE_NAME (type);
  1357.       tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl));
  1358.       if (tmpl)
  1359.         {
  1360.           t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec;
  1361.           t->bindings = TREE_VALUE (tmpl);
  1362.         }
  1363.       type = DECL_CONTEXT (decl);
  1364.     }
  1365.       if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
  1366.       || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
  1367.     {
  1368.       if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
  1369.         my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type,
  1370.                 233);
  1371.  
  1372.       /* Inline functions can be compiled immediately.  Other functions
  1373.          will be output separately, so if we're in interface-only mode,
  1374.          punt them now, or output them now if we're doing implementations
  1375.          and we know no overrides will exist.  Otherwise, we delay until
  1376.          end-of-file, to see if the definition is really required.  */
  1377.       if (DECL_INLINE (decl))
  1378.         /* delay_to_eof == 0 */;
  1379.       else if (current_class_type && !interface_unknown)
  1380.         {
  1381.           if (interface_only)
  1382.         {
  1383. #if 0
  1384.           print_node_brief (stderr, "\ndiscarding text for ", decl, 0);
  1385. #endif
  1386.           if (t->can_free)
  1387.             obstack_free (&inline_text_obstack, t->buf);
  1388.           DECL_PENDING_INLINE_INFO (decl) = 0;
  1389.           return;
  1390.         }
  1391.         }
  1392.       /* Don't delay the processing of virtual functions.  */
  1393.       else if (DECL_VINDEX (decl) == NULL_TREE)
  1394.         delay_to_eof = 1;
  1395.     }
  1396.       else
  1397.     my_friendly_abort (58);
  1398.     }
  1399.  
  1400.   if (delay_to_eof)
  1401.     {
  1402.       extern struct pending_inline *pending_template_expansions;
  1403.  
  1404.       if (t->can_free)
  1405.     {
  1406.       char *free_to = t->buf;
  1407.       t->buf = (char *) obstack_copy (&permanent_obstack, t->buf,
  1408.                       t->len + 1);
  1409.       t = (struct pending_inline *) obstack_copy (&permanent_obstack, 
  1410.                               (char *)t, sizeof (*t));
  1411.       obstack_free (&inline_text_obstack, free_to);
  1412.     }
  1413.       inlines = &pending_template_expansions;
  1414.       t->can_free = 0;
  1415.     }
  1416.   else
  1417.     {
  1418.       inlines = &pending_inlines;
  1419.       DECL_PENDING_INLINE_INFO (decl) = t;
  1420.     }
  1421.  
  1422.   /* Because we use obstacks, we must process these in precise order.  */
  1423.   t->next = *inlines;
  1424.   *inlines = t;
  1425. }
  1426.  
  1427. void reinit_parse_for_block ();
  1428.  
  1429. void
  1430. reinit_parse_for_method (yychar, decl)
  1431.      int yychar;
  1432.      tree decl;
  1433. {
  1434.   int len;
  1435.   int starting_lineno = lineno;
  1436.   char *starting_filename = input_filename;
  1437.  
  1438.   reinit_parse_for_block (yychar, &inline_text_obstack, 0);
  1439.  
  1440.   len = obstack_object_size (&inline_text_obstack);
  1441.   current_base_init_list = NULL_TREE;
  1442.   current_member_init_list = NULL_TREE;
  1443.   if (decl == void_type_node
  1444.       || (current_class_type && TYPE_REDEFINED (current_class_type)))
  1445.     {
  1446.       /* Happens when we get two declarations of the same
  1447.      function in the same scope.  */
  1448.       char *buf = obstack_finish (&inline_text_obstack);
  1449.       obstack_free (&inline_text_obstack, buf);
  1450.       return;
  1451.     }
  1452.   else
  1453.     {
  1454.       struct pending_inline *t;
  1455.       char *buf = obstack_finish (&inline_text_obstack);
  1456.  
  1457.       t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
  1458.                            sizeof (struct pending_inline));
  1459.       t->buf = buf;
  1460.       t->len = len;
  1461.       t->lineno = starting_lineno;
  1462.       t->filename = starting_filename;
  1463.       t->token = YYEMPTY;
  1464.       t->can_free = 1;
  1465.       t->deja_vu = 0;
  1466.       t->interface = ((interface_unknown || processing_template_defn)
  1467.               ? 1
  1468.               : (interface_only ? 0 : 2));
  1469.       store_pending_inline (decl, t);
  1470.     }
  1471. }
  1472.  
  1473. /* Consume a block -- actually, a method or template definition beginning
  1474.    with `:' or `{' -- and save it away on the specified obstack.
  1475.  
  1476.    Argument IS_TEMPLATE indicates which set of error messages should be
  1477.    output if something goes wrong.  This should really be cleaned up somehow,
  1478.    without loss of clarity.  */
  1479. void
  1480. reinit_parse_for_block (yychar, obstackp, is_template)
  1481.      int yychar;
  1482.      struct obstack *obstackp;
  1483.      int is_template;
  1484. {
  1485.   register int c = 0;
  1486.   int blev = 1;
  1487.   int starting_lineno = lineno;
  1488.   char *starting_filename = input_filename;
  1489.   int len;
  1490.   int look_for_semicolon = 0;
  1491.  
  1492.   if (yychar == '{')
  1493.     obstack_1grow (obstackp, '{');
  1494.   else if (yychar == '=')
  1495.     {
  1496.       look_for_semicolon = 1;
  1497.     }
  1498.   else
  1499.     {
  1500.       if (yychar != ':' && (yychar != RETURN || is_template))
  1501.     {
  1502.       yyerror (is_template
  1503.            ? "parse error in template specification"
  1504.            : "parse error in method specification");
  1505.       yychar = '{';
  1506.     }
  1507.       obstack_1grow (obstackp, yychar);
  1508.       while (c >= 0)
  1509.     {
  1510.       int this_lineno = lineno;
  1511.  
  1512.       c = yynextch ();
  1513.  
  1514.       /* Don't lose our cool if there are lots of comments.  */
  1515.       if (lineno == this_lineno)
  1516.         ;
  1517.       else if (lineno - this_lineno < 10 /* + strlen (input_filename) */)
  1518.         {
  1519.           int i;
  1520.           for (i = lineno - this_lineno; i > 0; i--)
  1521.         obstack_1grow (obstackp, '\n');
  1522.         }
  1523.       else
  1524.         {
  1525.           char buf[12];
  1526.           sprintf (buf, "\n# %d \"", lineno);
  1527.           len = strlen (buf);
  1528.           obstack_grow (obstackp, buf, len);
  1529.  
  1530.           len = strlen (input_filename);
  1531.           obstack_grow (obstackp, input_filename, len);
  1532.           obstack_1grow (obstackp, '\"');
  1533.           obstack_1grow (obstackp, '\n');
  1534.         }
  1535.  
  1536.       /* strings must be read differently than text.  */
  1537.       if (c == '\"')
  1538.         {
  1539.           obstack_1grow (obstackp, c);
  1540.           consume_string (obstackp);
  1541.           c = yynextch ();
  1542.         }
  1543.       while (c > ' ')    /* ASCII dependent! */
  1544.         {
  1545.           obstack_1grow (obstackp, c);
  1546.           if (c == '{') goto main_loop;
  1547.           if (c == '\"')
  1548.         consume_string (obstackp);
  1549.           if (c == ';')
  1550.         {
  1551.           error (is_template
  1552.              ? "template body missing"
  1553.              : "function body for constructor missing");
  1554.           obstack_1grow (obstackp, '{');
  1555.           obstack_1grow (obstackp, '}');
  1556.           len += 2;
  1557.           goto done;
  1558.         }
  1559.           c = getch ();
  1560.         }
  1561.       if (c == '\n')
  1562.         lineno++;
  1563.       obstack_1grow (obstackp, c);
  1564.     }
  1565.       if (c == EOF)
  1566.     {
  1567.       error_with_file_and_line (starting_filename,
  1568.                     starting_lineno,
  1569.                     "end of file read inside definition");
  1570.     }      
  1571.     }
  1572.  
  1573.  main_loop:
  1574.   while (c >= 0)
  1575.     {
  1576.       int this_lineno = lineno;
  1577.  
  1578.       c = skip_white_space (getch ());
  1579.  
  1580.       /* Don't lose our cool if there are lots of comments.  */
  1581.       if (lineno - this_lineno)
  1582.     if (lineno - this_lineno == 1)
  1583.       obstack_1grow (obstackp, '\n');
  1584.     else
  1585.       {
  1586.         char buf[12];
  1587.         sprintf (buf, "\n# %d \"", lineno);
  1588.         len = strlen (buf);
  1589.         obstack_grow (obstackp, buf, len);
  1590.  
  1591.         len = strlen (input_filename);
  1592.         obstack_grow (obstackp, input_filename, len);
  1593.         obstack_1grow (obstackp, '\"');
  1594.         obstack_1grow (obstackp, '\n');
  1595.       }
  1596.  
  1597.       while (c > ' ')
  1598.     {
  1599.       obstack_1grow (obstackp, c);
  1600.       if (c == '{') blev++;
  1601.       else if (c == '}')
  1602.         {
  1603.           blev--;
  1604.           if (blev == 0 && !look_for_semicolon)
  1605.         goto done;
  1606.         }
  1607.       else if (c == '\"')
  1608.         consume_string (obstackp);
  1609.       else if (c == ';' && look_for_semicolon && blev == 0)
  1610.         goto done;
  1611.       c = getch ();
  1612.     }
  1613.       if (c == '\n')
  1614.     lineno++;
  1615.       obstack_1grow (obstackp, c);
  1616.     }
  1617.  done:
  1618.   obstack_1grow (obstackp, '\0');
  1619. }
  1620.  
  1621. /* Build a default function named NAME for type TYPE.
  1622.    KIND says what to build.
  1623.  
  1624.    When KIND == 0, build default destructor.
  1625.    When KIND == 1, build virtual destructor.
  1626.    When KIND == 2, build default constructor.
  1627.    When KIND == 3, build default X(const X&) constructor.
  1628.    When KIND == 4, build default X(X&) constructor.  */
  1629.  
  1630. tree
  1631. cons_up_default_function (type, name, kind)
  1632.      tree type, name;
  1633.      int kind;
  1634. {
  1635.   extern tree void_list_node, constructor_name ();
  1636.   int len;
  1637.   tree declspecs = NULL_TREE;
  1638.   tree fn, args;
  1639.   tree argtype;
  1640.  
  1641.   name = constructor_name (name);
  1642.   switch (kind)
  1643.     {
  1644.       /* Destructors.  */
  1645.     case 1:
  1646.       declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
  1647.       /* Fall through...  */
  1648.     case 0:
  1649.       name = build_parse_node (BIT_NOT_EXPR, name);
  1650.       /* Fall through...  */
  1651.     case 2:
  1652.       /* Default constructor.  */
  1653.       args = void_list_node;
  1654.       break;
  1655.  
  1656.     case 3:
  1657.       type = build_type_variant (type, 1, 0);
  1658.       /* Fall through...  */
  1659.     case 4:
  1660.       argtype = build_reference_type (type);
  1661.       args = tree_cons (NULL_TREE,
  1662.             build_tree_list (hash_tree_chain (argtype, NULL_TREE),
  1663.                      get_identifier ("arg")),
  1664.             void_list_node);
  1665.       break;
  1666.  
  1667.     default:
  1668.       my_friendly_abort (59);
  1669.     }
  1670.  
  1671.   fn = start_method (declspecs,
  1672.              build_parse_node (CALL_EXPR, name, args, NULL_TREE),
  1673.              NULL_TREE);
  1674.   if (fn == void_type_node)
  1675.     return fn;
  1676.  
  1677.   current_base_init_list = NULL_TREE;
  1678.   current_member_init_list = NULL_TREE;
  1679.  
  1680.   len = 3;
  1681.  
  1682.   {
  1683.     struct pending_inline *t;
  1684.  
  1685.     t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
  1686.                          sizeof (struct pending_inline));
  1687.     t->buf = default_def;
  1688.     t->len = len;
  1689.     t->lineno = lineno;
  1690.     t->filename = input_filename;
  1691.     t->token = YYEMPTY;
  1692.     t->can_free = 0;
  1693.     t->deja_vu = 0;
  1694.     t->interface = ((interface_unknown || processing_template_defn)
  1695.             ? 1
  1696.             : (interface_only ? 0 : 2));
  1697.     store_pending_inline (fn, t);
  1698.     /* We make this declaration private (static in the C sense).  */
  1699.     TREE_PUBLIC (fn) = 0;
  1700.   }
  1701.   finish_method (fn);
  1702.   DECL_CLASS_CONTEXT (fn) = type;
  1703.   /* Show that this function was generated by the compiler.  */
  1704.   DECL_SOURCE_LINE (fn) = 0;
  1705.   return fn;
  1706. }
  1707.  
  1708. /* Heuristic to tell whether the user is missing a semicolon
  1709.    after a struct or enum declaration.  Emit an error message
  1710.    if we know the user has blown it.  */
  1711. void
  1712. check_for_missing_semicolon (type)
  1713.      tree type;
  1714. {
  1715.   if (yychar < 0)
  1716.     yychar = yylex ();
  1717.  
  1718.   if (yychar > 255
  1719.       && yychar != IDENTIFIER
  1720.       && yychar != TYPENAME)
  1721.     {
  1722.       if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
  1723.     error ("semicolon missing after %s declaration",
  1724.            TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
  1725.       else
  1726.     error ("semicolon missing after declaration of `%s'",
  1727.            TYPE_NAME_STRING (type));
  1728.       shadow_tag (build_tree_list (0, type));
  1729.     }
  1730.   /* Could probably also hack cases where class { ... } f (); appears.  */
  1731.   clear_anon_tags ();
  1732. }
  1733.  
  1734. void
  1735. note_got_semicolon (type)
  1736.      tree type;
  1737. {
  1738.   if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
  1739.     my_friendly_abort (60);
  1740.   if (IS_AGGR_TYPE (type))
  1741.     CLASSTYPE_GOT_SEMICOLON (type) = 1;
  1742. }
  1743.  
  1744. void
  1745. note_list_got_semicolon (declspecs)
  1746.      tree declspecs;
  1747. {
  1748.   tree link;
  1749.  
  1750.   for (link = declspecs; link; link = TREE_CHAIN (link))
  1751.     {
  1752.       tree type = TREE_VALUE (link);
  1753.       if (TREE_CODE_CLASS (TREE_CODE (type)) == 't')
  1754.     note_got_semicolon (type);
  1755.     }
  1756.   clear_anon_tags ();
  1757. }
  1758.  
  1759. /* If C is not whitespace, return C.
  1760.    Otherwise skip whitespace and return first nonwhite char read.  */
  1761.  
  1762. static int
  1763. skip_white_space (c)
  1764.      register int c;
  1765. {
  1766.   for (;;)
  1767.     {
  1768.       switch (c)
  1769.     {
  1770.     case '\n':
  1771.       c = check_newline ();
  1772.       break;
  1773.  
  1774.     case ' ':
  1775.     case '\t':
  1776.     case '\f':
  1777.     case '\r':
  1778.     case '\v':
  1779.     case '\b':
  1780.       do
  1781.         c = getch ();
  1782.       while (c == ' ' || c == '\t');
  1783.       break;
  1784.  
  1785.     case '\\':
  1786.       c = getch ();
  1787.       if (c == '\n')
  1788.         lineno++;
  1789.       else
  1790.         error ("stray '\\' in program");
  1791.       c = getch ();
  1792.       break;
  1793.  
  1794.     default:
  1795.       return (c);
  1796.     }
  1797.     }
  1798. }
  1799.  
  1800.  
  1801. #ifdef MPW
  1802. #pragma segment CPLEX01
  1803. #endif
  1804.  
  1805.  
  1806. /* Make the token buffer longer, preserving the data in it.
  1807.    P should point to just beyond the last valid character in the old buffer.
  1808.    The value we return is a pointer to the new buffer
  1809.    at a place corresponding to P.  */
  1810.  
  1811. static char *
  1812. extend_token_buffer (p)
  1813.      char *p;
  1814. {
  1815.   int offset = p - token_buffer;
  1816.  
  1817.   maxtoken = maxtoken * 2 + 10;
  1818.   token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
  1819.  
  1820.   return token_buffer + offset;
  1821. }
  1822.  
  1823. static int
  1824. get_last_nonwhite_on_line ()
  1825. {
  1826.   register int c;
  1827.  
  1828.   /* Is this the last nonwhite stuff on the line?  */
  1829.   if (nextchar >= 0)
  1830.     c = nextchar, nextchar = -1;
  1831.   else
  1832.     c = getch ();
  1833.  
  1834.   while (c == ' ' || c == '\t')
  1835.     c = getch ();
  1836.   return c;
  1837. }
  1838.  
  1839. /* At the beginning of a line, increment the line number
  1840.    and process any #-directive on this line.
  1841.    If the line is a #-directive, read the entire line and return a newline.
  1842.    Otherwise, return the line's first non-whitespace character.  */
  1843.  
  1844. int
  1845. check_newline ()
  1846. {
  1847.   register int c;
  1848.   register int token;
  1849.  
  1850.   lineno++;
  1851.  
  1852.   /* Read first nonwhite char on the line.  */
  1853.  
  1854.   do
  1855.     c = getch ();
  1856.   while (c == ' ' || c == '\t');
  1857.  
  1858.   if (c != '#')
  1859.     {
  1860.       /* If not #, return it so caller will use it.  */
  1861.       return c;
  1862.     }
  1863.  
  1864.   /* Read first nonwhite char after the `#'.  */
  1865.  
  1866.   do
  1867.     c = getch ();
  1868.   while (c == ' ' || c == '\t');
  1869.  
  1870.   /* If a letter follows, then if the word here is `line', skip
  1871.      it and ignore it; otherwise, ignore the line, with an error
  1872.      if the word isn't `pragma'.  */
  1873.  
  1874.   if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
  1875.     {
  1876.       if (c == 'p')
  1877.     {
  1878.       if (getch () == 'r'
  1879.           && getch () == 'a'
  1880.           && getch () == 'g'
  1881.           && getch () == 'm'
  1882.           && getch () == 'a')
  1883.         {
  1884.           /* Read first nonwhite char after the `#pragma'.  */
  1885.  
  1886.           do
  1887.         c = getch ();
  1888.           while (c == ' ' || c == '\t');
  1889.  
  1890.           if (c == 'v'
  1891.           && getch () == 't'
  1892.           && getch () == 'a'
  1893.           && getch () == 'b'
  1894.           && getch () == 'l'
  1895.           && getch () == 'e'
  1896.           && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  1897.         {
  1898.           extern tree pending_vtables;
  1899.  
  1900.           /* More follows: it must be a string constant (class name).  */
  1901.           token = real_yylex ();
  1902.           if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
  1903.             {
  1904.               error ("invalid #pragma vtable");
  1905.               goto skipline;
  1906.             }
  1907.           if (write_virtuals != 2)
  1908.             {
  1909.               warning ("use `+e2' option to enable #pragma vtable");
  1910.               goto skipline;
  1911.             }
  1912.           pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables);
  1913.           if (nextchar < 0)
  1914.             nextchar = getch ();
  1915.           c = nextchar;
  1916.           if (c != '\n')
  1917.             warning ("trailing characters ignored");
  1918.         }
  1919.           else if (c == 'u'
  1920.                && getch () == 'n'
  1921.                && getch () == 'i'
  1922.                && getch () == 't'
  1923.                && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  1924.         {
  1925.           /* More follows: it must be a string constant (unit name).  */
  1926.           token = real_yylex ();
  1927.           if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
  1928.             {
  1929.               error ("invalid #pragma unit");
  1930.               goto skipline;
  1931.             }
  1932.           current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
  1933.           current_unit_language = current_lang_name;
  1934.           if (nextchar < 0)
  1935.             nextchar = getch ();
  1936.           c = nextchar;
  1937.           if (c != '\n')
  1938.             warning ("trailing characters ignored");
  1939.         }
  1940.           else if (c == 'i')
  1941.         {
  1942.           tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
  1943.           c = getch ();
  1944.  
  1945.           if (c == 'n'
  1946.               && getch () == 't'
  1947.               && getch () == 'e'
  1948.               && getch () == 'r'
  1949.               && getch () == 'f'
  1950.               && getch () == 'a'
  1951.               && getch () == 'c'
  1952.               && getch () == 'e'
  1953.               && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  1954.             {
  1955.               /* read to newline.  */
  1956.               while (c != '\n')
  1957.             c = getch ();
  1958.  
  1959.               write_virtuals = 3;
  1960.  
  1961.               if (impl_file_chain == 0)
  1962.             {
  1963.               char *filename;
  1964.               tree fi;
  1965.  
  1966.               /* If this is zero at this point, then we are
  1967.                  auto-implementing.  */
  1968.               if (main_input_filename == 0)
  1969.                 main_input_filename = input_filename;
  1970.  
  1971.               filename = FILE_NAME_NONDIRECTORY (main_input_filename);
  1972.               fi = get_time_identifier (filename);
  1973.               fi = IDENTIFIER_CLASS_VALUE (fi);
  1974.               TREE_INT_CST_LOW (fi) = 0;
  1975.               TREE_INT_CST_HIGH (fi) = 1;
  1976.               /* Get default.  */
  1977.               impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
  1978.               impl_file_chain->filename = filename;
  1979.               impl_file_chain->next = 0;
  1980.             }
  1981.  
  1982.               interface_only = interface_strcmp (input_filename);
  1983.               interface_unknown = 0;
  1984.               TREE_INT_CST_LOW (fileinfo) = interface_only;
  1985.               TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
  1986.             }
  1987.           else if (c == 'm'
  1988.                && getch () == 'p'
  1989.                && getch () == 'l'
  1990.                && getch () == 'e'
  1991.                && getch () == 'm'
  1992.                && getch () == 'e'
  1993.                && getch () == 'n'
  1994.                && getch () == 't'
  1995.                && getch () == 'a'
  1996.                && getch () == 't'
  1997.                && getch () == 'i'
  1998.                && getch () == 'o'
  1999.                && getch () == 'n'
  2000.                && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2001.             {
  2002.               char *main_filename = main_input_filename ? main_input_filename : input_filename;
  2003.  
  2004.               while (c == ' ' || c == '\t')
  2005.             c = getch ();
  2006.               if (c != '\n')
  2007.             {
  2008.               put_back (c);
  2009.               token = real_yylex ();
  2010.               if (token != STRING
  2011.                   || TREE_CODE (yylval.ttype) != STRING_CST)
  2012.                 {
  2013.                   error ("invalid `#pragma implementation'");
  2014.                   goto skipline;
  2015.                 }
  2016.               main_filename = TREE_STRING_POINTER (yylval.ttype);
  2017.             }
  2018.               main_filename = FILE_NAME_NONDIRECTORY (main_filename);
  2019.  
  2020.               /* read to newline.  */
  2021.               while (c != '\n')
  2022.             c = getch ();
  2023.  
  2024.               if (write_virtuals == 3)
  2025.             {
  2026.               struct impl_files *ifiles = impl_file_chain;
  2027.               while (ifiles)
  2028.                 {
  2029.                   if (! strcmp (ifiles->filename, main_filename))
  2030.                 break;
  2031.                   ifiles = ifiles->next;
  2032.                 }
  2033.               if (ifiles == 0)
  2034.                 {
  2035.                   ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
  2036.                   ifiles->filename = main_filename;
  2037.                   ifiles->next = impl_file_chain;
  2038.                   impl_file_chain = ifiles;
  2039.                 }
  2040.             }
  2041.               else if ((main_input_filename != 0
  2042.                 && ! strcmp (main_input_filename, input_filename))
  2043.                    || ! strcmp (input_filename, main_filename))
  2044.             {
  2045.               write_virtuals = 3;
  2046.               if (impl_file_chain == 0)
  2047.                 {
  2048.                   impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
  2049.                   impl_file_chain->filename = main_filename;
  2050.                   impl_file_chain->next = 0;
  2051.                 }
  2052.             }
  2053.               else
  2054.             error ("`#pragma implementation' can only appear at top-level");
  2055.               interface_only = 0;
  2056.               /* We make this non-zero so that we infer decl linkage
  2057.              in the impl file only for variables first declared
  2058.              in the interface file.  */
  2059.               interface_unknown = 1;
  2060.               TREE_INT_CST_LOW (fileinfo) = interface_only;
  2061.               TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
  2062.             }
  2063.         }
  2064.         }
  2065.       goto skipline;
  2066.     }
  2067.       else if (c == 'd')
  2068.     {
  2069.       if (getch () == 'e'
  2070.           && getch () == 'f'
  2071.           && getch () == 'i'
  2072.           && getch () == 'n'
  2073.           && getch () == 'e'
  2074.           && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2075.         {
  2076. #ifdef DWARF_DEBUGGING_INFO
  2077.           if ((debug_info_level == DINFO_LEVEL_VERBOSE)
  2078.           && (write_symbols == DWARF_DEBUG))
  2079.             dwarfout_define (lineno, get_directive_line (finput));
  2080. #endif /* DWARF_DEBUGGING_INFO */
  2081.           goto skipline;
  2082.         }
  2083.     }
  2084.       else if (c == 'u')
  2085.     {
  2086.       if (getch () == 'n'
  2087.           && getch () == 'd'
  2088.           && getch () == 'e'
  2089.           && getch () == 'f'
  2090.           && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2091.         {
  2092. #ifdef DWARF_DEBUGGING_INFO
  2093.           if ((debug_info_level == DINFO_LEVEL_VERBOSE)
  2094.           && (write_symbols == DWARF_DEBUG))
  2095.             dwarfout_undef (lineno, get_directive_line (finput));
  2096. #endif /* DWARF_DEBUGGING_INFO */
  2097.           goto skipline;
  2098.         }
  2099.     }
  2100.       else if (c == 'l')
  2101.     {
  2102.       if (getch () == 'i'
  2103.           && getch () == 'n'
  2104.           && getch () == 'e'
  2105.           && ((c = getch ()) == ' ' || c == '\t'))
  2106.         goto linenum;
  2107.     }
  2108.       else if (c == 'i')
  2109.     {
  2110.       if (getch () == 'd'
  2111.           && getch () == 'e'
  2112.           && getch () == 'n'
  2113.           && getch () == 't'
  2114.           && ((c = getch ()) == ' ' || c == '\t'))
  2115.         {
  2116. #ifdef ASM_OUTPUT_IDENT
  2117.               extern FILE *asm_out_file;
  2118. #endif
  2119.           /* #ident.  The pedantic warning is now in cccp.c.  */
  2120.  
  2121.           /* Here we have just seen `#ident '.
  2122.          A string constant should follow.  */
  2123.  
  2124.           while (c == ' ' || c == '\t')
  2125.         c = getch ();
  2126.  
  2127.           /* If no argument, ignore the line.  */
  2128.           if (c == '\n')
  2129.         return c;
  2130.  
  2131.           put_back (c);
  2132.           token = real_yylex ();
  2133.           if (token != STRING
  2134.           || TREE_CODE (yylval.ttype) != STRING_CST)
  2135.         {
  2136.           error ("invalid #ident");
  2137.           goto skipline;
  2138.         }
  2139.  
  2140.           if (! flag_no_ident)
  2141.         {
  2142. #ifdef ASM_OUTPUT_IDENT
  2143.           ASM_OUTPUT_IDENT (asm_out_file,
  2144.                     TREE_STRING_POINTER (yylval.ttype));
  2145. #endif
  2146.         }
  2147.  
  2148.           /* Skip the rest of this line.  */
  2149.           goto skipline;
  2150.         }
  2151.     }
  2152.       else if (c == 'n')
  2153.     {
  2154.       if (getch () == 'e'
  2155.           && getch () == 'w'
  2156.           && getch () == 'w'
  2157.           && getch () == 'o'
  2158.           && getch () == 'r'
  2159.           && getch () == 'l'
  2160.           && getch () == 'd'
  2161.           && ((c = getch ()) == ' ' || c == '\t'))
  2162.         {
  2163.           /* Used to test incremental compilation.  */
  2164.           sorry ("#pragma newworld");
  2165.           goto skipline;
  2166.         }
  2167.     }
  2168.       error ("undefined or invalid # directive");
  2169.       goto skipline;
  2170.     }
  2171.  
  2172. linenum:
  2173.   /* Here we have either `#line' or `# <nonletter>'.
  2174.      In either case, it should be a line number; a digit should follow.  */
  2175.  
  2176.   while (c == ' ' || c == '\t')
  2177.     c = getch ();
  2178.  
  2179.   /* If the # is the only nonwhite char on the line,
  2180.      just ignore it.  Check the new newline.  */
  2181.   if (c == '\n')
  2182.     return c;
  2183.  
  2184.   /* Something follows the #; read a token.  */
  2185.  
  2186.   put_back (c);
  2187.   token = real_yylex ();
  2188.  
  2189.   if (token == CONSTANT
  2190.       && TREE_CODE (yylval.ttype) == INTEGER_CST)
  2191.     {
  2192.       int old_lineno = lineno;
  2193.       int used_up = 0;
  2194.       /* subtract one, because it is the following line that
  2195.      gets the specified number */
  2196.  
  2197.       int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
  2198.       c = get_last_nonwhite_on_line ();
  2199.       if (c == '\n')
  2200.     {
  2201.       /* No more: store the line number and check following line.  */
  2202.       lineno = l;
  2203.       return c;
  2204.     }
  2205.       put_back (c);
  2206.  
  2207.       /* More follows: it must be a string constant (filename).  */
  2208.  
  2209.       /* Read the string constant, but don't treat \ as special.  */
  2210.       ignore_escape_flag = 1;
  2211.       token = real_yylex ();
  2212.       ignore_escape_flag = 0;
  2213.  
  2214.       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
  2215.     {
  2216.       error ("invalid #line");
  2217.       goto skipline;
  2218.     }
  2219.  
  2220.       /* Changing files again.  This means currently collected time
  2221.      is charged against header time, and body time starts back
  2222.      at 0.  */
  2223.       if (flag_detailed_statistics)
  2224.     {
  2225.       int this_time = my_get_run_time ();
  2226.       tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
  2227.       header_time += this_time - body_time;
  2228.       TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
  2229.         += this_time - body_time;
  2230.       this_filename_time = time_identifier;
  2231.       body_time = this_time;
  2232.     }
  2233.  
  2234.       if (flag_cadillac)
  2235.     cadillac_note_source ();
  2236.  
  2237.       input_filename
  2238.     = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
  2239.       strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
  2240.       lineno = l;
  2241.       GNU_xref_file (input_filename);
  2242.  
  2243.       /* Each change of file name
  2244.      reinitializes whether we are now in a system header.  */
  2245.       in_system_header = 0;
  2246.  
  2247.       if (main_input_filename == 0)
  2248.     {
  2249.       struct impl_files *ifiles = impl_file_chain;
  2250.  
  2251.       if (ifiles)
  2252.         {
  2253.           while (ifiles->next)
  2254.         ifiles = ifiles->next;
  2255.           ifiles->filename = FILE_NAME_NONDIRECTORY (input_filename);
  2256.         }
  2257.  
  2258.       main_input_filename = input_filename;
  2259.       if (write_virtuals == 3)
  2260.         walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
  2261.     }
  2262.  
  2263.       extract_interface_info ();
  2264.  
  2265.       c = get_last_nonwhite_on_line ();
  2266.       if (c == '\n')
  2267.     {
  2268.       if (flag_cadillac)
  2269.         cadillac_switch_source (-1);
  2270.       return c;
  2271.     }
  2272.       put_back (c);
  2273.  
  2274.       token = real_yylex ();
  2275.       used_up = 0;
  2276.  
  2277.       /* `1' after file name means entering new file.
  2278.      `2' after file name means just left a file.  */
  2279.  
  2280.       if (token == CONSTANT
  2281.       && TREE_CODE (yylval.ttype) == INTEGER_CST)
  2282.     {
  2283.       if (TREE_INT_CST_LOW (yylval.ttype) == 1)
  2284.         {
  2285.           /* Pushing to a new file.  */
  2286.           struct file_stack *p
  2287.         = (struct file_stack *) xmalloc (sizeof (struct file_stack));
  2288.           input_file_stack->line = old_lineno;
  2289.           p->next = input_file_stack;
  2290.           p->name = input_filename;
  2291.           input_file_stack = p;
  2292.           input_file_stack_tick++;
  2293. #ifdef DWARF_DEBUGGING_INFO
  2294.           if (debug_info_level == DINFO_LEVEL_VERBOSE
  2295.           && write_symbols == DWARF_DEBUG)
  2296.         dwarfout_start_new_source_file (input_filename);
  2297. #endif /* DWARF_DEBUGGING_INFO */
  2298.  
  2299.           used_up = 1;
  2300.           if (flag_cadillac)
  2301.         cadillac_push_source ();
  2302.         }
  2303.       else if (TREE_INT_CST_LOW (yylval.ttype) == 2)
  2304.         {
  2305.           /* Popping out of a file.  */
  2306.           if (input_file_stack->next)
  2307.         {
  2308.           struct file_stack *p = input_file_stack;
  2309.  
  2310.           if (flag_cadillac)
  2311.             cadillac_pop_source ();
  2312.  
  2313.           input_file_stack = p->next;
  2314.           free (p);
  2315.           input_file_stack_tick++;
  2316. #ifdef DWARF_DEBUGGING_INFO
  2317.           if (debug_info_level == DINFO_LEVEL_VERBOSE
  2318.               && write_symbols == DWARF_DEBUG)
  2319.             dwarfout_resume_previous_source_file (input_file_stack->line);
  2320. #endif /* DWARF_DEBUGGING_INFO */
  2321.         }
  2322.           else
  2323.         error ("#-lines for entering and leaving files don't match");
  2324.  
  2325.           used_up = 1;
  2326.         }
  2327.     }
  2328.       else if (flag_cadillac)
  2329.     cadillac_switch_source (-1);
  2330.  
  2331.       /* If we have handled a `1' or a `2',
  2332.      see if there is another number to read.  */
  2333.       if (used_up)
  2334.     {
  2335.       c = get_last_nonwhite_on_line ();
  2336.       if (c == '\n')
  2337.         {
  2338.           if (flag_cadillac)
  2339.         cadillac_switch_source (-1);
  2340.           return c;
  2341.         }
  2342.       put_back (c);
  2343.  
  2344.       token = real_yylex ();
  2345.       used_up = 0;
  2346.     }
  2347.  
  2348.       /* `3' after file name means this is a system header file.  */
  2349.  
  2350.       if (token == CONSTANT
  2351.       && TREE_CODE (yylval.ttype) == INTEGER_CST
  2352.       && TREE_INT_CST_LOW (yylval.ttype) == 3)
  2353.     in_system_header = 1;
  2354.  
  2355.       /* If NEXTCHAR is not end of line, we don't care what it is.  */
  2356.       if (nextchar == '\n')
  2357.     return '\n';
  2358.     }
  2359.   else
  2360.     error ("invalid #-line");
  2361.  
  2362.   /* skip the rest of this line.  */
  2363.  skipline:
  2364.   if (c == '\n')
  2365.     return c;
  2366.   while ((c = getch ()) != EOF && c != '\n');
  2367.   return c;
  2368. }
  2369.  
  2370. #if 0
  2371. #define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
  2372. #define isdigit(char) (char >= '0' && char <= '9')
  2373. #else
  2374. #include <ctype.h>
  2375. #endif
  2376.  
  2377. #define ENDFILE -1  /* token that represents end-of-file */
  2378.  
  2379. /* Read an escape sequence, returning its equivalent as a character,
  2380.    or store 1 in *ignore_ptr if it is backslash-newline.  */
  2381.  
  2382. static int
  2383. readescape (ignore_ptr)
  2384.      int *ignore_ptr;
  2385. {
  2386.   register int c = getch ();
  2387.   register int code;
  2388.   register unsigned count;
  2389.   unsigned firstdig;
  2390.   int nonnull;
  2391.  
  2392.   switch (c)
  2393.     {
  2394.     case 'x':
  2395.       if (warn_traditional)
  2396.     warning ("the meaning of `\\x' varies with -traditional");
  2397.  
  2398.       if (flag_traditional)
  2399.     return c;
  2400.  
  2401.       code = 0;
  2402.       count = 0;
  2403.       nonnull = 0;
  2404.       while (1)
  2405.     {
  2406.       c = getch ();
  2407.       if (! isxdigit (c))
  2408.         {
  2409.           put_back (c);
  2410.           break;
  2411.         }
  2412.       code *= 16;
  2413.       if (c >= 'a' && c <= 'f')
  2414.         code += c - 'a' + 10;
  2415.       if (c >= 'A' && c <= 'F')
  2416.         code += c - 'A' + 10;
  2417.       if (c >= '0' && c <= '9')
  2418.         code += c - '0';
  2419.       if (code != 0 || count != 0)
  2420.         {
  2421.           if (count == 0)
  2422.         firstdig = code;
  2423.           count++;
  2424.         }
  2425.       nonnull = 1;
  2426.     }
  2427.       if (! nonnull)
  2428.     error ("\\x used with no following hex digits");
  2429.       else if (count == 0)
  2430.     /* Digits are all 0's.  Ok.  */
  2431.     ;
  2432.       else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
  2433.            || (count > 1
  2434.            && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
  2435.                <= firstdig)))
  2436.     warning ("hex escape out of range");
  2437.       return code;
  2438.  
  2439.     case '0':  case '1':  case '2':  case '3':  case '4':
  2440.     case '5':  case '6':  case '7':
  2441.       code = 0;
  2442.       count = 0;
  2443.       while ((c <= '7') && (c >= '0') && (count++ < 3))
  2444.     {
  2445.       code = (code * 8) + (c - '0');
  2446.       c = getch ();
  2447.     }
  2448.       put_back (c);
  2449.       return code;
  2450.  
  2451.     case '\\': case '\'': case '"':
  2452.       return c;
  2453.  
  2454.     case '\n':
  2455.       lineno++;
  2456.       *ignore_ptr = 1;
  2457.       return 0;
  2458.  
  2459.     case 'n':
  2460.       return TARGET_NEWLINE;
  2461.  
  2462.     case 't':
  2463.       return TARGET_TAB;
  2464.  
  2465.     case 'r':
  2466.       return TARGET_CR;
  2467.  
  2468.     case 'f':
  2469.       return TARGET_FF;
  2470.  
  2471.     case 'b':
  2472.       return TARGET_BS;
  2473.  
  2474.     case 'a':
  2475.       if (warn_traditional)
  2476.     warning ("the meaning of `\\a' varies with -traditional");
  2477.  
  2478.       if (flag_traditional)
  2479.     return c;
  2480.       return TARGET_BELL;
  2481.  
  2482.     case 'v':
  2483.       return TARGET_VT;
  2484.  
  2485.     case 'e':
  2486.     case 'E':
  2487.       if (pedantic)
  2488.     pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
  2489.       return 033;
  2490.  
  2491.     case '?':
  2492.       return c;
  2493.  
  2494.       /* `\(', etc, are used at beginning of line to avoid confusing Emacs.  */
  2495.     case '(':
  2496.     case '{':
  2497.     case '[':
  2498.       if (pedantic)
  2499.     pedwarn ("unknown escape sequence `\\%c'", c);
  2500.       return c;
  2501.     }
  2502. #ifdef APPLE_HAX
  2503.     /* backslash-p needs to return a special code so that the string
  2504.        constructor can leave a hole and patch in the string length later. */
  2505.     /* (What happens if this char appears in a char constant?) */
  2506.     if(c == 'p' && flag_apple) 
  2507.       return -2;
  2508. #endif /* APPLE_HAX */
  2509.   if (c >= 040 && c < 0177)
  2510.     pedwarn ("unknown escape sequence `\\%c'", c);
  2511.   else
  2512.     pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
  2513.   return c;
  2514. }
  2515.  
  2516. /* Value is 1 if we should try to make the next identifier look like a
  2517.    typename (when it may be a local variable or a class variable).
  2518.    Value is 0 if we treat this name in a default fashion.
  2519.    Value is -1 if we must not see a type name.  */
  2520. int looking_for_typename = 0;
  2521.  
  2522. void
  2523. dont_see_typename ()
  2524. {
  2525.   looking_for_typename = -1;
  2526.   if (yychar == TYPENAME || yychar == PTYPENAME)
  2527.     {
  2528.       yychar = IDENTIFIER;
  2529.       lastiddecl = 0;
  2530.     }
  2531. }
  2532.  
  2533. #ifdef __GNUC__
  2534. extern __inline int identifier_type ();
  2535. __inline
  2536. #endif
  2537. int
  2538. identifier_type (decl)
  2539.      tree decl;
  2540. {
  2541.   if (TREE_CODE (decl) == TEMPLATE_DECL
  2542.       && DECL_TEMPLATE_IS_CLASS (decl))
  2543.     return PTYPENAME;
  2544.   if (TREE_CODE (decl) != TYPE_DECL)
  2545.     return IDENTIFIER;
  2546.   return TYPENAME;
  2547. }
  2548.  
  2549. void
  2550. see_typename ()
  2551. {
  2552.   looking_for_typename = 0;
  2553.   if (yychar == IDENTIFIER)
  2554.     {
  2555.       lastiddecl = lookup_name (yylval.ttype, -1);
  2556.       if (lastiddecl == 0)
  2557.     {
  2558.       if (flag_labels_ok)
  2559.         lastiddecl = IDENTIFIER_LABEL_VALUE (yylval.ttype);
  2560.     }
  2561.       else
  2562.     yychar = identifier_type (lastiddecl);
  2563.     }
  2564. }
  2565.  
  2566. tree do_identifier (token)
  2567.      register tree token;
  2568. {
  2569.   register tree id = lastiddecl;
  2570.  
  2571. #if defined(APPLE_HAX) && defined(IMPORT_DECL)
  2572.   if(token) IMPORT_DECL(token);
  2573. #endif
  2574.  
  2575.   if (yychar == YYEMPTY)
  2576.     yychar = yylex ();
  2577.   /* Scope class declarations before global
  2578.      declarations.  */
  2579.   if (id == IDENTIFIER_GLOBAL_VALUE (token)
  2580.       && current_class_type != 0
  2581.       && TYPE_SIZE (current_class_type) == 0
  2582.       && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE)
  2583.     {
  2584.       /* Could be from one of the base classes.  */
  2585.       tree field = lookup_field (current_class_type, token, 1, 0);
  2586.       if (field == 0)
  2587.     ;
  2588.       else if (field == error_mark_node)
  2589.     /* We have already generated the error message.
  2590.        But we still want to return this value.  */
  2591.     id = lookup_field (current_class_type, token, 0, 0);
  2592.       else if (TREE_CODE (field) == VAR_DECL
  2593.            || TREE_CODE (field) == CONST_DECL)
  2594.     id = field;
  2595.       else if (TREE_CODE (field) != FIELD_DECL)
  2596.     my_friendly_abort (61);
  2597.       else
  2598.     {
  2599.       error_with_decl (field, "invalid use of member `%s' from base class `%s'",
  2600.                TYPE_NAME_STRING (DECL_FIELD_CONTEXT (field)));
  2601.       id = error_mark_node;
  2602.       return id;
  2603.     }
  2604.     }
  2605.  
  2606.   if (!id || id == error_mark_node)
  2607.     {
  2608.       if (id == error_mark_node && current_class_type != NULL_TREE)
  2609.     {
  2610.       id = lookup_nested_field (token);
  2611.       /* In lookup_nested_field(), we marked this so we can gracefully
  2612.          leave this whole mess.  */
  2613.       if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
  2614.         return id;
  2615.     }
  2616.       if (yychar == '(' || yychar == LEFT_RIGHT)
  2617.     {
  2618.       id = implicitly_declare (token);
  2619.     }
  2620.       else if (current_function_decl == 0)
  2621.     {
  2622.       error ("`%s' undeclared, outside of functions",
  2623.          IDENTIFIER_POINTER (token));
  2624.       id = error_mark_node;
  2625.     }
  2626.       else
  2627.     {
  2628.       if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
  2629.           || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
  2630.         {
  2631.           extern int undeclared_variable_notice;
  2632.  
  2633.           error ("`%s' undeclared (first use this function)",
  2634.              IDENTIFIER_POINTER (token));
  2635.  
  2636.           if (! undeclared_variable_notice)
  2637.         {
  2638.           error ("(Each undeclared identifier is reported only once");
  2639.           error ("for each function it appears in.)");
  2640.           undeclared_variable_notice = 1;
  2641.         }
  2642.         }
  2643.       id = error_mark_node;
  2644.       /* Prevent repeated error messages.  */
  2645.       IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
  2646.       SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
  2647.     }
  2648.     }
  2649.   /* TREE_USED is set in `hack_identifier'.  */
  2650.   if (TREE_CODE (id) == CONST_DECL)
  2651.     {
  2652.       if (IDENTIFIER_CLASS_VALUE (token) == id)
  2653.     {
  2654.       /* Check visibility.  */
  2655.       enum visibility_type visibility
  2656.         = compute_visibility (TYPE_BINFO (current_class_type), id);
  2657.       if (visibility == visibility_private)
  2658.         error_with_decl (id, "enum `%s' is private");
  2659.       /* protected is OK, since it's an enum of `this'.  */
  2660.     }
  2661.       id = DECL_INITIAL (id);
  2662.     }
  2663.   else id = hack_identifier (id, token, yychar);
  2664.   return id;
  2665. }
  2666.  
  2667. tree
  2668. identifier_typedecl_value (node)
  2669.      tree node;
  2670. {
  2671.   tree t, type;
  2672.   type = IDENTIFIER_TYPE_VALUE (node);
  2673.   if (type == NULL_TREE)
  2674.     return NULL_TREE;
  2675. #define do(X) \
  2676.   { \
  2677.     t = (X); \
  2678.     if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
  2679.       return t; \
  2680.   }
  2681.   do (IDENTIFIER_LOCAL_VALUE (node));
  2682.   do (IDENTIFIER_CLASS_VALUE (node));
  2683.   do (IDENTIFIER_GLOBAL_VALUE (node));
  2684. #undef do
  2685.   /* Will this one ever happen?  */
  2686.   if (TYPE_NAME (type))
  2687.     return TYPE_NAME (type);
  2688.   my_friendly_abort (62);
  2689. }
  2690.  
  2691. struct try_type
  2692. {
  2693.   tree *node_var;
  2694.   char unsigned_flag;
  2695.   char long_flag;
  2696.   char long_long_flag;
  2697. };
  2698.  
  2699. struct try_type type_sequence[] = 
  2700. {
  2701.   { &integer_type_node, 0, 0, 0},
  2702.   { &unsigned_type_node, 1, 0, 0},
  2703.   { &long_integer_type_node, 0, 1, 0},
  2704.   { &long_unsigned_type_node, 1, 1, 0},
  2705.   { &long_long_integer_type_node, 0, 1, 1},
  2706.   { &long_long_unsigned_type_node, 1, 1, 1}
  2707. };
  2708.  
  2709. int
  2710. real_yylex ()
  2711. {
  2712.   tree tmp;
  2713.   register int c;
  2714.   register int value;
  2715.   int wide_flag = 0;
  2716.   int dollar_seen = 0;
  2717.   int i;
  2718.  
  2719.   if (nextchar >= 0)
  2720.     c = nextchar, nextchar = -1;
  2721.   else
  2722.     c = getch ();
  2723.  
  2724.   /* Effectively do c = skip_white_space (c)
  2725.      but do it faster in the usual cases.  */
  2726.   while (1)
  2727.     switch (c)
  2728.       {
  2729.       case ' ':
  2730.       case '\t':
  2731.       case '\f':
  2732.       case '\v':
  2733.       case '\b':
  2734.     c = getch ();
  2735.     break;
  2736.  
  2737.       case '\r':
  2738.     /* Call skip_white_space so we can warn if appropriate.  */
  2739.  
  2740.       case '\n':
  2741.       case '/':
  2742.       case '\\':
  2743.     c = skip_white_space (c);
  2744.       default:
  2745.     goto found_nonwhite;
  2746.       }
  2747.  found_nonwhite:
  2748.  
  2749.   token_buffer[0] = c;
  2750.   token_buffer[1] = 0;
  2751.  
  2752. /*  yylloc.first_line = lineno; */
  2753.  
  2754.   switch (c)
  2755.     {
  2756.     case EOF:
  2757.       token_buffer[0] = '\0';
  2758.       end_of_file = 1;
  2759.       if (input_redirected ())
  2760.     value = END_OF_SAVED_INPUT;
  2761.       else if (do_pending_expansions ())
  2762.     /* this will set yychar for us */
  2763.     return yychar;
  2764.       else
  2765.     value = ENDFILE;
  2766.       break;
  2767.  
  2768.     case '$':
  2769.       if (dollars_in_ident)
  2770.     {
  2771.       dollar_seen = 1;
  2772.       goto letter;
  2773.     }
  2774.       value = '$';
  2775.       goto done;
  2776.  
  2777.     case 'L':
  2778.       /* Capital L may start a wide-string or wide-character constant.  */
  2779.       {
  2780.     register int c = getch ();
  2781.     if (c == '\'')
  2782.       {
  2783.         wide_flag = 1;
  2784.         goto char_constant;
  2785.       }
  2786.     if (c == '"')
  2787.       {
  2788.         wide_flag = 1;
  2789.         goto string_constant;
  2790.       }
  2791.     put_back (c);
  2792.       }
  2793.  
  2794.     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  2795.     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  2796.     case 'K':          case 'M':  case 'N':  case 'O':
  2797.     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  2798.     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  2799.     case 'Z':
  2800.     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  2801.     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  2802.     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  2803.     case 'p':  case 'q':  case 'r':  case 's':  case 't':
  2804.     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  2805.     case 'z':
  2806.     case '_':
  2807.     letter:
  2808.       {
  2809.     register char *p;
  2810.  
  2811.     p = token_buffer;
  2812.     if (input == 0)
  2813.       {
  2814.         /* We know that `token_buffer' can hold at least on char,
  2815.            so we install C immediately.
  2816.            We may have to read the value in `putback_char', so call
  2817.            `getch' once.  */
  2818.         *p++ = c;
  2819.         c = getch ();
  2820.  
  2821.         /* Make this run fast.  We know that we are reading straight
  2822.            from FINPUT in this case (since identifiers cannot straddle
  2823.            input sources.  */
  2824.         while (isalnum (c) || (c == '_') || c == '$')
  2825.           {
  2826.         if (p >= token_buffer + maxtoken)
  2827.           p = extend_token_buffer (p);
  2828.         if (c == '$' && ! dollars_in_ident)
  2829.           break;
  2830.  
  2831.         *p++ = c;
  2832.         c = getc (finput);
  2833.           }
  2834.       }
  2835.     else
  2836.       {
  2837.         /* We know that `token_buffer' can hold at least on char,
  2838.            so we install C immediately.  */
  2839.         *p++ = c;
  2840.         c = getch ();
  2841.  
  2842.         while (isalnum (c) || (c == '_') || c == '$')
  2843.           {
  2844.         if (p >= token_buffer + maxtoken)
  2845.           p = extend_token_buffer (p);
  2846.         if (c == '$' && ! dollars_in_ident)
  2847.           break;
  2848.  
  2849.         *p++ = c;
  2850.         c = getch ();
  2851.           }
  2852.       }
  2853.  
  2854.     *p = 0;
  2855.     nextchar = c;
  2856.  
  2857.     value = IDENTIFIER;
  2858.     yylval.itype = 0;
  2859.  
  2860.       /* Try to recognize a keyword.  Uses minimum-perfect hash function */
  2861.  
  2862.     {
  2863.       register struct resword *ptr;
  2864.  
  2865.       if (ptr = is_reserved_word (token_buffer, p - token_buffer))
  2866.         {
  2867.           if (ptr->rid)
  2868.         {
  2869.           tree old_ttype = ridpointers[(int) ptr->rid];
  2870.  
  2871.           /* If this provides a type for us, then revert lexical
  2872.              state to standard state.  */
  2873.           if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
  2874.               && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
  2875.               && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
  2876.             looking_for_typename = 0;
  2877.           else if (ptr->token == AGGR || ptr->token == ENUM)
  2878.             looking_for_typename = 1;
  2879.  
  2880.           /* Check if this is a language-type declaration.
  2881.              Just glimpse the next non-white character.  */
  2882.           nextchar = skip_white_space (nextchar);
  2883.           if (nextchar == '"')
  2884.             {
  2885.               /* We are looking at a string.  Complain
  2886.              if the token before the string is no `extern'.
  2887.              
  2888.              Could cheat some memory by placing this string
  2889.              on the temporary_, instead of the saveable_
  2890.              obstack.  */
  2891.  
  2892.               if (ptr->rid != RID_EXTERN)
  2893.             error ("invalid modifier `%s' for language string",
  2894.                    ptr->name);
  2895.               real_yylex ();
  2896.               value = EXTERN_LANG_STRING;
  2897.               yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype));
  2898.               break;
  2899.             }
  2900.           if (ptr->token == VISSPEC)
  2901.             {
  2902.               switch (ptr->rid)
  2903.             {
  2904.             case RID_PUBLIC:
  2905.               yylval.itype = visibility_public;
  2906.               break;
  2907.             case RID_PRIVATE:
  2908.               yylval.itype = visibility_private;
  2909.               break;
  2910.             case RID_PROTECTED:
  2911.               yylval.itype = visibility_protected;
  2912.               break;
  2913.             default:
  2914.               my_friendly_abort (63);
  2915.             }
  2916.             }
  2917.           else
  2918.             yylval.ttype = old_ttype;
  2919.         }
  2920.           value = (int) ptr->token;
  2921.         }
  2922.     }
  2923.  
  2924.     /* If we did not find a keyword, look for an identifier
  2925.        (or a typename).  */
  2926.  
  2927.     if (value == IDENTIFIER || value == TYPESPEC)
  2928.       GNU_xref_ref (current_function_decl, token_buffer);
  2929.  
  2930.     if (value == IDENTIFIER)
  2931.       {
  2932.         tmp = get_identifier (token_buffer);
  2933.  
  2934. #ifndef VMS
  2935.         /* Make sure that user does not collide with our internal
  2936.            naming scheme.  */
  2937.         if (JOINER == '$'
  2938.         && dollar_seen
  2939.         && (THIS_NAME_P (tmp)
  2940.             || VPTR_NAME_P (tmp)
  2941.             || DESTRUCTOR_NAME_P (tmp)
  2942.             || VTABLE_NAME_P (tmp)
  2943.             || TEMP_NAME_P (tmp)
  2944.             || ANON_AGGRNAME_P (tmp)
  2945.             || ANON_PARMNAME_P (tmp)))
  2946.           warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
  2947.                token_buffer);
  2948. #endif
  2949.  
  2950.         yylval.ttype = tmp;
  2951.       }
  2952.     if (value == NEW && ! global_bindings_p ())
  2953.       {
  2954.         looking_for_typename = 1;
  2955.         value = NEW;
  2956.         goto done;
  2957.       }
  2958.       }
  2959.       break;
  2960.  
  2961.     case '.':
  2962.       {
  2963.     register int c1 = getch ();
  2964.     token_buffer[0] = c;
  2965.     token_buffer[1] = c1;
  2966.     if (c1 == '*')
  2967.       {
  2968.         value = DOT_STAR;
  2969.         token_buffer[2] = 0;
  2970.         goto done;
  2971.       }
  2972.     if (c1 == '.')
  2973.       {
  2974.         c1 = getch ();
  2975.         if (c1 == '.')
  2976.           {
  2977.         token_buffer[2] = c1;
  2978.         token_buffer[3] = 0;
  2979.         value = ELLIPSIS;
  2980.         goto done;
  2981.           }
  2982.         nextchar = c1;
  2983.         token_buffer[2] = '\0';
  2984.         value = RANGE;
  2985.         goto done;
  2986.       }
  2987.     if (isdigit (c1))
  2988.       {
  2989.         put_back (c1);
  2990.         goto resume_numerical_scan;
  2991.       }
  2992.     nextchar = c1;
  2993.     value = '.';
  2994.     token_buffer[1] = 0;
  2995.     goto done;
  2996.       }
  2997.     case '0':  case '1':
  2998.     /* Optimize for most frequent case.  */
  2999.       {
  3000.     register int c1 = getch ();
  3001.     if (! isalnum (c1) && c1 != '.')
  3002.       {
  3003.         /* Terminate string.  */
  3004.         token_buffer[0] = c;
  3005.         token_buffer[1] = 0;
  3006.         if (c == '0')
  3007.           yylval.ttype = integer_zero_node;
  3008.         else
  3009.           yylval.ttype = integer_one_node;
  3010.         nextchar = c1;
  3011.         value = CONSTANT;
  3012.         goto done;
  3013.       }
  3014.     put_back (c1);
  3015.       }
  3016.       /* fall through... */
  3017.               case '2':  case '3':  case '4':
  3018.     case '5':  case '6':  case '7':  case '8':  case '9':
  3019.     resume_numerical_scan:
  3020.       {
  3021.     register char *p;
  3022.     int base = 10;
  3023.     int count = 0;
  3024.     int largest_digit = 0;
  3025.     int numdigits = 0;
  3026.     /* for multi-precision arithmetic,
  3027.        we store only 8 live bits in each short.  */
  3028.     short shorts[MAX_SHORTS];
  3029.     int overflow = 0;
  3030.  
  3031.     enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
  3032.       = NOT_FLOAT;
  3033.  
  3034.     p = token_buffer;
  3035.     *p++ = c;
  3036.  
  3037.     for (count = 0; count < MAX_SHORTS; count++)
  3038.       shorts[count] = 0;
  3039.  
  3040.     if (c == '0')
  3041.       {
  3042.         *p++ = (c = getch ());
  3043.         if ((c == 'x') || (c == 'X'))
  3044.           {
  3045.         base = 16;
  3046.         *p++ = (c = getch ());
  3047.           }
  3048.         /* Leading 0 forces octal unless the 0 is the only digit.  */
  3049.         else if (c >= '0' && c <= '9')
  3050.           {
  3051.         base = 8;
  3052.         numdigits++;
  3053.           }
  3054.         else
  3055.           numdigits++;
  3056.       }
  3057.  
  3058.     /* Read all the digits-and-decimal-points.  */
  3059.  
  3060.     while (c == '.'
  3061.            || (isalnum (c) && (c != 'l') && (c != 'L')
  3062.            && (c != 'u') && (c != 'U')
  3063.            && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
  3064.       {
  3065.         if (c == '.')
  3066.           {
  3067.         if (base == 16)
  3068.           error ("floating constant may not be in radix 16");
  3069.         if (floatflag == AFTER_POINT)
  3070.           {
  3071.             error ("malformed floating constant");
  3072.             floatflag = TOO_MANY_POINTS;
  3073.           }
  3074.         else
  3075.           floatflag = AFTER_POINT;
  3076.  
  3077.         base = 10;
  3078.         *p++ = c = getch ();
  3079.         /* Accept '.' as the start of a floating-point number
  3080.            only when it is followed by a digit.
  3081.            Otherwise, unread the following non-digit
  3082.            and use the '.' as a structural token.  */
  3083.         if (p == token_buffer + 2 && !isdigit (c))
  3084.           {
  3085.             if (c == '.')
  3086.               {
  3087.             c = getch ();
  3088.             if (c == '.')
  3089.               {
  3090.                 *p++ = '.';
  3091.                 *p = '\0';
  3092.                 value = ELLIPSIS;
  3093.                 goto done;
  3094.               }
  3095.             nextchar = c;
  3096.             token_buffer[2] = '\0';
  3097.             value = RANGE;
  3098.             goto done;
  3099.               }
  3100.             nextchar = c;
  3101.             token_buffer[1] = '\0';
  3102.             value = '.';
  3103.             goto done;
  3104.           }
  3105.           }
  3106.         else
  3107.           {
  3108.         /* It is not a decimal point.
  3109.            It should be a digit (perhaps a hex digit).  */
  3110.  
  3111.         if (isdigit (c))
  3112.           {
  3113.             c = c - '0';
  3114.           }
  3115.         else if (base <= 10)
  3116.           {
  3117.             if ((c&~040) == 'E')
  3118.               {
  3119.             base = 10;
  3120.             floatflag = AFTER_POINT;
  3121.             break;   /* start of exponent */
  3122.               }
  3123.             error ("nondigits in number and not hexadecimal");
  3124.             c = 0;
  3125.           }
  3126.         else if (c >= 'a')
  3127.           {
  3128.             c = c - 'a' + 10;
  3129.           }
  3130.         else
  3131.           {
  3132.             c = c - 'A' + 10;
  3133.           }
  3134.         if (c >= largest_digit)
  3135.           largest_digit = c;
  3136.         numdigits++;
  3137.  
  3138.         for (count = 0; count < MAX_SHORTS; count++)
  3139.           {
  3140.             shorts[count] *= base;
  3141.             if (count)
  3142.               {
  3143.             shorts[count] += (shorts[count-1] >> 8);
  3144.             shorts[count-1] &= (1<<8)-1;
  3145.               }
  3146.             else shorts[0] += c;
  3147.           }
  3148.  
  3149.         if (shorts[MAX_SHORTS - 1] >= 1<<8
  3150.             || shorts[MAX_SHORTS - 1] < - (1 << 8))
  3151.           overflow = TRUE;
  3152.  
  3153.         if (p >= token_buffer + maxtoken - 3)
  3154.           p = extend_token_buffer (p);
  3155.         *p++ = (c = getch ());
  3156.           }
  3157.       }
  3158.  
  3159.     if (numdigits == 0)
  3160.       error ("numeric constant with no digits");
  3161.  
  3162.     if (largest_digit >= base)
  3163.       error ("numeric constant contains digits beyond the radix");
  3164.  
  3165.     /* Remove terminating char from the token buffer and delimit the string */
  3166.     *--p = 0;
  3167.  
  3168.     if (floatflag != NOT_FLOAT)
  3169.       {
  3170.         tree type = double_type_node;
  3171.         char f_seen = 0;
  3172.         char l_seen = 0;
  3173.         REAL_VALUE_TYPE value;
  3174.         jmp_buf handler;
  3175.  
  3176.         /* Read explicit exponent if any, and put it in tokenbuf.  */
  3177.  
  3178.         if ((c == 'e') || (c == 'E'))
  3179.           {
  3180.         if (p >= token_buffer + maxtoken - 3)
  3181.           p = extend_token_buffer (p);
  3182.         *p++ = c;
  3183.         c = getch ();
  3184.         if ((c == '+') || (c == '-'))
  3185.           {
  3186.             *p++ = c;
  3187.             c = getch ();
  3188.           }
  3189.         if (! isdigit (c))
  3190.           error ("floating constant exponent has no digits");
  3191.             while (isdigit (c))
  3192.           {
  3193.             if (p >= token_buffer + maxtoken - 3)
  3194.               p = extend_token_buffer (p);
  3195.             *p++ = c;
  3196.             c = getch ();
  3197.           }
  3198.           }
  3199.  
  3200.         *p = 0;
  3201.         errno = 0;
  3202.  
  3203.         /* Convert string to a double, checking for overflow.  */
  3204.         if (setjmp (handler))
  3205.           {
  3206.         error ("floating constant out of range");
  3207.         value = dconst0;
  3208.           }
  3209.         else
  3210.           {
  3211.         set_float_handler (handler);
  3212.         value = REAL_VALUE_ATOF (token_buffer);
  3213.         set_float_handler (NULL);
  3214.           }
  3215. #ifdef ERANGE
  3216.         if (errno == ERANGE && !flag_traditional)
  3217.           {
  3218.         char *p1 = token_buffer;
  3219.         /* Check for "0.0" and variants;
  3220.            SunOS 4 spuriously returns ERANGE for them.  */
  3221.         while (*p1 == '0') p1++;
  3222.         if (*p1 == '.')
  3223.           {
  3224.             p1++;
  3225.             while (*p1 == '0') p1++;
  3226.           }
  3227.         if (*p1 == 'e' || *p1 == 'E')
  3228.           {
  3229.             /* with significand==0, ignore the exponent */
  3230.             p1++;
  3231.             while (*p1 != 0) p1++;
  3232.           }
  3233.         /* ERANGE is also reported for underflow,
  3234.            so test the value to distinguish overflow from that.  */
  3235.         if (*p1 != 0 && (value > 1.0 || value < -1.0))
  3236.           warning ("floating point number exceeds range of `double'");
  3237.           }
  3238. #endif
  3239.  
  3240.         /* Read the suffixes to choose a data type.  */
  3241.         while (1)
  3242.           {
  3243.         if (c == 'f' || c == 'F')
  3244.           {
  3245.             if (f_seen)
  3246.               error ("two `f's in floating constant");
  3247.             f_seen = 1;
  3248.             type = float_type_node;
  3249.             value = real_value_truncate (TYPE_MODE (type), value);
  3250.           }
  3251.         else if (c == 'l' || c == 'L')
  3252.           {
  3253.             if (l_seen)
  3254.               error ("two `l's in floating constant");
  3255.             l_seen = 1;
  3256.             type = long_double_type_node;
  3257.           }
  3258.         else
  3259.           {
  3260.             if (isalnum (c))
  3261.               {
  3262.             error ("garbage at end of number");
  3263.             while (isalnum (c))
  3264.               {
  3265.                 if (p >= token_buffer + maxtoken - 3)
  3266.                   p = extend_token_buffer (p);
  3267.                 *p++ = c;
  3268.                 c = getch ();
  3269.               }
  3270.               }
  3271.             break;
  3272.           }
  3273.         if (p >= token_buffer + maxtoken - 3)
  3274.           p = extend_token_buffer (p);
  3275.         *p++ = c;
  3276.         c = getch ();
  3277.           }
  3278.  
  3279.         /* Create a node with determined type and value.  */
  3280.         yylval.ttype = build_real (type, value);
  3281.  
  3282.         put_back (c);
  3283.         *p = 0;
  3284.       }
  3285.     else
  3286.       {
  3287.         tree type;
  3288.         HOST_WIDE_INT high, low;
  3289.         int spec_unsigned = 0;
  3290.         int spec_long = 0;
  3291.         int spec_long_long = 0;
  3292.  
  3293.         while (1)
  3294.           {
  3295.         if (c == 'u' || c == 'U')
  3296.           {
  3297.             if (spec_unsigned)
  3298.               error ("two `u's in integer constant");
  3299.             spec_unsigned = 1;
  3300.           }
  3301.         else if (c == 'l' || c == 'L')
  3302.           {
  3303.             if (spec_long)
  3304.               {
  3305.             if (spec_long_long)
  3306.               error ("three `l's in integer constant");
  3307.             else if (pedantic)
  3308.               pedwarn ("ANSI C++ forbids long long integer constants");
  3309.             spec_long_long = 1;
  3310.               }
  3311.             spec_long = 1;
  3312.           }
  3313.         else
  3314.           {
  3315.             if (isalnum (c))
  3316.               {
  3317.             error ("garbage at end of number");
  3318.             while (isalnum (c))
  3319.               {
  3320.                 if (p >= token_buffer + maxtoken - 3)
  3321.                   p = extend_token_buffer (p);
  3322.                 *p++ = c;
  3323.                 c = getch ();
  3324.               }
  3325.               }
  3326.             break;
  3327.           }
  3328.         if (p >= token_buffer + maxtoken - 3)
  3329.           p = extend_token_buffer (p);
  3330.         *p++ = c;
  3331.         c = getch ();
  3332.           }
  3333.  
  3334.         put_back (c);
  3335.  
  3336.         /* ??? This code assumes that everything but long long is 32-bits.
  3337.            Probably this code needs to be replaced with code similar
  3338.            to that in c-lex.c, but I don't want to do it. -- RK.  */
  3339.  
  3340.         if ((overflow || shorts[7] || shorts[6] || shorts[5] || shorts[4])
  3341.         && !spec_long_long)
  3342.           warning ("integer constant out of range");
  3343.  
  3344.         /* If it won't fit in a signed long long, make it unsigned.
  3345.            We can't distinguish based on the tree node because
  3346.            any integer constant fits any long long type.  */
  3347.         if (shorts[7] >= (1<<8))
  3348.           spec_unsigned = 1;
  3349.  
  3350.         /* This is simplified by the fact that our constant
  3351.            is always positive.  */
  3352.         high = low = 0;
  3353.  
  3354.         for (i = 0; i < MAX_SHORTS / 2; i++)
  3355.           {
  3356.         high |= (HOST_WIDE_INT) shorts[i + MAX_SHORTS / 2] << (i * 8);
  3357.         low |= (HOST_WIDE_INT) shorts[i] << (i * 8);
  3358.           }
  3359.         
  3360.         yylval.ttype = build_int_2 (low, high);
  3361.  
  3362. #if 0
  3363.         /* Find the first allowable type that the value fits in.  */
  3364.         type = 0;
  3365.         for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
  3366.          i++)
  3367.           if (!(spec_long && !type_sequence[i].long_flag)
  3368.           && !(spec_long_long && !type_sequence[i].long_long_flag)
  3369.           && !(spec_unsigned && !type_sequence[i].unsigned_flag)
  3370.           /* A hex or octal constant traditionally is unsigned.  */
  3371.           && !(base != 10 && flag_traditional
  3372.                && !type_sequence[i].unsigned_flag)
  3373.           /* A decimal constant can't be unsigned int
  3374.              unless explicitly specified.  */
  3375.           && !(base == 10 && !spec_unsigned
  3376.                && *type_sequence[i].node_var == unsigned_type_node))
  3377.         if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
  3378.           {
  3379.             type = *type_sequence[i].node_var;
  3380.             break;
  3381.           }
  3382.         if (flag_traditional && type == long_unsigned_type_node
  3383.         && !spec_unsigned)
  3384.           type = long_integer_type_node;
  3385.           
  3386.         if (type == 0)
  3387.           {
  3388.         type = long_long_integer_type_node;
  3389.         warning ("integer constant out of range");
  3390.           }
  3391.  
  3392.         /* Warn about some cases where the type of a given constant
  3393.            changes from traditional C to ANSI C.  */
  3394.         if (warn_traditional)
  3395.           {
  3396.         tree other_type = 0;
  3397.  
  3398.         /* This computation is the same as the previous one
  3399.            except that flag_traditional is used backwards.  */
  3400.         for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
  3401.              i++)
  3402.           if (!(spec_long && !type_sequence[i].long_flag)
  3403.               && !(spec_long_long && !type_sequence[i].long_long_flag)
  3404.               && !(spec_unsigned && !type_sequence[i].unsigned_flag)
  3405.               /* A hex or octal constant traditionally is unsigned.  */
  3406.               && !(base != 10 && !flag_traditional
  3407.                && !type_sequence[i].unsigned_flag)
  3408.               /* A decimal constant can't be unsigned int
  3409.              unless explicitly specified.  */
  3410.               && !(base == 10 && !spec_unsigned
  3411.                && *type_sequence[i].node_var == unsigned_type_node))
  3412.             if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
  3413.               {
  3414.             other_type = *type_sequence[i].node_var;
  3415.             break;
  3416.               }
  3417.         if (!flag_traditional && type == long_unsigned_type_node
  3418.             && !spec_unsigned)
  3419.           type = long_integer_type_node;
  3420.           
  3421.         if (other_type != 0 && other_type != type)
  3422.           {
  3423.             if (flag_traditional)
  3424.               warning ("type of integer constant would be different without -traditional");
  3425.             else
  3426.               warning ("type of integer constant would be different with -traditional");
  3427.           }
  3428.           }
  3429.  
  3430. #else /* 1 */
  3431.         if (!spec_long && !spec_unsigned
  3432.         && !(flag_traditional && base != 10)
  3433.         && int_fits_type_p (yylval.ttype, integer_type_node))
  3434.           {
  3435. #if 0
  3436.         if (warn_traditional && base != 10)
  3437.           warning ("small nondecimal constant becomes signed in ANSI C++");
  3438. #endif
  3439.         type = integer_type_node;
  3440.           }
  3441.         else if (!spec_long && (base != 10 || spec_unsigned)
  3442.              && int_fits_type_p (yylval.ttype, unsigned_type_node))
  3443.           {
  3444.         /* Nondecimal constants try unsigned even in traditional C.  */
  3445.         type = unsigned_type_node;
  3446.           }
  3447.  
  3448.         else if (!spec_unsigned && !spec_long_long
  3449.              && int_fits_type_p (yylval.ttype, long_integer_type_node))
  3450.           type = long_integer_type_node;
  3451.  
  3452.         else if (! spec_long_long
  3453.              && int_fits_type_p (yylval.ttype,
  3454.                      long_unsigned_type_node))
  3455.           {
  3456. #if 0
  3457.         if (warn_traditional && !spec_unsigned)
  3458.           warning ("large integer constant becomes unsigned in ANSI C++");
  3459. #endif
  3460.         if (flag_traditional && !spec_unsigned)
  3461.           type = long_integer_type_node;
  3462.         else
  3463.           type = long_unsigned_type_node;
  3464.           }
  3465.  
  3466.         else if (! spec_unsigned
  3467.              && int_fits_type_p (yylval.ttype,
  3468.                      long_long_integer_type_node))
  3469.           type = long_long_integer_type_node;
  3470.  
  3471.         else if (int_fits_type_p (yylval.ttype,
  3472.                       long_long_unsigned_type_node))
  3473.           {
  3474. #if 0
  3475.         if (warn_traditional && !spec_unsigned)
  3476.           warning ("large nondecimal constant is unsigned in ANSI C++");
  3477. #endif
  3478.  
  3479.         if (flag_traditional && !spec_unsigned)
  3480.           type = long_long_integer_type_node;
  3481.         else
  3482.           type = long_long_unsigned_type_node;
  3483.           }
  3484.  
  3485.         else
  3486.           {
  3487.         type = long_long_integer_type_node;
  3488.         warning ("integer constant out of range");
  3489.           }
  3490. #endif
  3491.  
  3492.         TREE_TYPE (yylval.ttype) = type;
  3493.         *p = 0;
  3494.       }
  3495.  
  3496.     value = CONSTANT; break;
  3497.       }
  3498.  
  3499.     case '\'':
  3500.     char_constant:
  3501.       {
  3502.     register int result = 0;
  3503.     register int num_chars = 0;
  3504.     unsigned width = TYPE_PRECISION (char_type_node);
  3505.     int max_chars;
  3506.  
  3507.     if (wide_flag)
  3508.       {
  3509.         width = WCHAR_TYPE_SIZE;
  3510. #ifdef MULTIBYTE_CHARS
  3511.         max_chars = MB_CUR_MAX;
  3512. #else
  3513.         max_chars = 1;
  3514. #endif
  3515.       }
  3516.     else
  3517.       max_chars = TYPE_PRECISION (integer_type_node) / width;
  3518.  
  3519.     while (1)
  3520.       {
  3521.       tryagain:
  3522.  
  3523.         c = getch ();
  3524.  
  3525.         if (c == '\'' || c == EOF)
  3526.           break;
  3527.  
  3528.         if (c == '\\')
  3529.           {
  3530.         int ignore = 0;
  3531.         c = readescape (&ignore);
  3532.         if (ignore)
  3533.           goto tryagain;
  3534.         if (width < HOST_BITS_PER_INT
  3535.             && (unsigned) c >= (1 << width))
  3536.           pedwarn ("escape sequence out of range for character");
  3537.           }
  3538.         else if (c == '\n')
  3539.           {
  3540.         if (pedantic)
  3541.           pedwarn ("ANSI C++ forbids newline in character constant");
  3542.         lineno++;
  3543.           }
  3544.  
  3545.         num_chars++;
  3546.         if (num_chars > maxtoken - 4)
  3547.           extend_token_buffer (token_buffer);
  3548.  
  3549.         token_buffer[num_chars] = c;
  3550.  
  3551.         /* Merge character into result; ignore excess chars.  */
  3552.         if (num_chars < max_chars + 1)
  3553.           {
  3554.         if (width < HOST_BITS_PER_INT)
  3555.           result = (result << width) | (c & ((1 << width) - 1));
  3556.         else
  3557.           result = c;
  3558.           }
  3559.       }
  3560.  
  3561.     token_buffer[num_chars + 1] = '\'';
  3562.     token_buffer[num_chars + 2] = 0;
  3563.  
  3564.     if (c != '\'')
  3565.       error ("malformatted character constant");
  3566.     else if (num_chars == 0)
  3567.       error ("empty character constant");
  3568.     else if (num_chars > max_chars)
  3569.       {
  3570.         num_chars = max_chars;
  3571.         error ("character constant too long");
  3572.       }
  3573. #ifdef APPLE_HAX
  3574.     /* Apple C doesn't mind multi-character constants, in fact things
  3575.        like resource IDs are preferred that way. */
  3576.     else if (num_chars != 1 && ! flag_traditional && !flag_apple)
  3577.       warning ("multi-character character constant");
  3578. #else
  3579.     else if (num_chars != 1 && ! flag_traditional)
  3580.       warning ("multi-character character constant");
  3581. #endif /* APPLE_HAX */
  3582.  
  3583.     /* If char type is signed, sign-extend the constant.  */
  3584.     if (! wide_flag)
  3585.       {
  3586.         int num_bits = num_chars * width;
  3587.         if (TREE_UNSIGNED (char_type_node)
  3588.         || ((result >> (num_bits - 1)) & 1) == 0)
  3589.           yylval.ttype
  3590.         = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
  3591.                      >> (HOST_BITS_PER_INT - num_bits)),
  3592.                    0);
  3593.         else
  3594.           yylval.ttype
  3595.         = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
  3596.                       >> (HOST_BITS_PER_INT - num_bits)),
  3597.                    -1);
  3598.         if (num_chars<=1)
  3599.           TREE_TYPE (yylval.ttype) = char_type_node;
  3600.         else
  3601.           TREE_TYPE (yylval.ttype) = integer_type_node;
  3602.       }
  3603.     else
  3604.       {
  3605. #ifdef MULTIBYTE_CHARS
  3606.         /* Set the initial shift state and convert the next sequence.  */
  3607.         result = 0;
  3608.         /* In all locales L'\0' is zero and mbtowc will return zero,
  3609.            so don't use it.  */
  3610.         if (num_chars > 1
  3611.         || (num_chars == 1 && token_buffer[1] != '\0'))
  3612.           {
  3613.         wchar_t wc;
  3614.         (void) mbtowc (NULL, NULL, 0);
  3615.         if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
  3616.           result = wc;
  3617.         else
  3618.           warning ("Ignoring invalid multibyte character");
  3619.           }
  3620. #endif
  3621.         yylval.ttype = build_int_2 (result, 0);
  3622.         TREE_TYPE (yylval.ttype) = wchar_type_node;
  3623.       }
  3624.  
  3625.     value = CONSTANT;
  3626.     break;
  3627.       }
  3628.  
  3629.     case '"':
  3630.     string_constant:
  3631.       {
  3632. #ifdef APPLE_HAX
  3633.     /* Flag to detect strings beginning with backslash-p */
  3634.     int pascalstring = FALSE;
  3635. #endif /* APPLE_HAX */
  3636.     register char *p;
  3637.  
  3638.     c = getch ();
  3639.     p = token_buffer + 1;
  3640.  
  3641.     while (c != '"' && c >= 0)
  3642.       {
  3643.         /* ignore_escape_flag is set for reading the filename in #line.  */
  3644.         if (!ignore_escape_flag && c == '\\')
  3645.           {
  3646.         int ignore = 0;
  3647.         c = readescape (&ignore);
  3648. #ifdef APPLE_HAX
  3649.         /* readescape returns a -2 to indicate it saw backslash-p */
  3650.         if (c == -2 && flag_apple)
  3651.           { pascalstring = TRUE; c = '\0';}
  3652. #endif /* APPLE_HAX */
  3653.         if (ignore)
  3654.           goto skipnewline;
  3655.         if (!wide_flag
  3656.             && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
  3657.             && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
  3658.           pedwarn ("escape sequence out of range for character");
  3659.           }
  3660.         else if (c == '\n')
  3661.           {
  3662.         if (pedantic)
  3663.           pedwarn ("ANSI C++ forbids newline in string constant");
  3664.         lineno++;
  3665.           }
  3666.  
  3667.         if (p == token_buffer + maxtoken)
  3668.           p = extend_token_buffer (p);
  3669.         *p++ = c;
  3670.  
  3671.       skipnewline:
  3672.         c = getch ();
  3673.         if (c == EOF) {
  3674.         error("Unterminated string");
  3675.         break;
  3676.         }
  3677.       }
  3678.     *p = 0;
  3679.  
  3680.     /* If we saw a backslash-p, jam the length in; subtracting 2 first
  3681.        (don't count length char, don't count 0 at end). */
  3682.     if (flag_apple && pascalstring)
  3683.       {
  3684.         token_buffer[1] = p - token_buffer - 2;
  3685.         if (wide_flag)
  3686.           warning("long string constants and \\p is probably not handled correctly.");
  3687.       }
  3688.  
  3689.     /* We have read the entire constant.
  3690.        Construct a STRING_CST for the result.  */
  3691.  
  3692.     if (wide_flag)
  3693.       {
  3694.         /* If this is a L"..." wide-string, convert the multibyte string
  3695.            to a wide character string.  */
  3696.         char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
  3697.         int len;
  3698.  
  3699. #ifdef MULTIBYTE_CHARS
  3700.         len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
  3701.         if ((unsigned) len >= (p - token_buffer))
  3702.           {
  3703.         warning ("Ignoring invalid multibyte string");
  3704.         len = 0;
  3705.           }
  3706.         bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
  3707. #else
  3708.         {
  3709.           union { long l; char c[sizeof (long)]; } u;
  3710.           int big_endian;
  3711.           char *wp, *cp;
  3712.  
  3713.           /* Determine whether host is little or big endian.  */
  3714.           u.l = 1;
  3715.           big_endian = u.c[sizeof (long) - 1];
  3716.           wp = widep + (big_endian ? WCHAR_BYTES - 1 : 0);
  3717.  
  3718.           bzero (widep, (p - token_buffer) * WCHAR_BYTES);
  3719.           for (cp = token_buffer + 1; cp < p; cp++)
  3720.         *wp = *cp, wp += WCHAR_BYTES;
  3721.           len = p - token_buffer - 1;
  3722.         }
  3723. #endif
  3724.         yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
  3725.         TREE_TYPE (yylval.ttype) = wchar_array_type_node;
  3726.       }
  3727.     else
  3728.       {
  3729.         yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
  3730.         TREE_TYPE (yylval.ttype) = char_array_type_node;
  3731.       }
  3732.  
  3733.     *p++ = '"';
  3734.     *p = 0;
  3735.  
  3736.     value = STRING; break;
  3737.       }
  3738.  
  3739.     case '+':
  3740.     case '-':
  3741.     case '&':
  3742.     case '|':
  3743.     case '<':
  3744.     case '>':
  3745.     case '*':
  3746.     case '/':
  3747.     case '%':
  3748.     case '^':
  3749.     case '!':
  3750.     case '=':
  3751.       {
  3752.     register int c1;
  3753.  
  3754.       combine:
  3755.  
  3756.     switch (c)
  3757.       {
  3758.       case '+':
  3759.         yylval.code = PLUS_EXPR; break;
  3760.       case '-':
  3761.         yylval.code = MINUS_EXPR; break;
  3762.       case '&':
  3763.         yylval.code = BIT_AND_EXPR; break;
  3764.       case '|':
  3765.         yylval.code = BIT_IOR_EXPR; break;
  3766.       case '*':
  3767.         yylval.code = MULT_EXPR; break;
  3768.       case '/':
  3769.         yylval.code = TRUNC_DIV_EXPR; break;
  3770.       case '%':
  3771.         yylval.code = TRUNC_MOD_EXPR; break;
  3772.       case '^':
  3773.         yylval.code = BIT_XOR_EXPR; break;
  3774.       case LSHIFT:
  3775.         yylval.code = LSHIFT_EXPR; break;
  3776.       case RSHIFT:
  3777.         yylval.code = RSHIFT_EXPR; break;
  3778.       case '<':
  3779.         yylval.code = LT_EXPR; break;
  3780.       case '>':
  3781.         yylval.code = GT_EXPR; break;
  3782.       }
  3783.  
  3784.     token_buffer[1] = c1 = getch ();
  3785.     token_buffer[2] = 0;
  3786.  
  3787.     if (c1 == '=')
  3788.       {
  3789.         switch (c)
  3790.           {
  3791.           case '<':
  3792.         value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
  3793.           case '>':
  3794.         value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
  3795.           case '!':
  3796.         value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
  3797.           case '=':
  3798.         value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
  3799.           }
  3800.         value = ASSIGN; goto done;
  3801.       }
  3802.     else if (c == c1)
  3803.       switch (c)
  3804.         {
  3805.         case '+':
  3806.           value = PLUSPLUS; goto done;
  3807.         case '-':
  3808.           value = MINUSMINUS; goto done;
  3809.         case '&':
  3810.           value = ANDAND; goto done;
  3811.         case '|':
  3812.           value = OROR; goto done;
  3813.         case '<':
  3814.           c = LSHIFT;
  3815.           goto combine;
  3816.         case '>':
  3817.           c = RSHIFT;
  3818.           goto combine;
  3819.         }
  3820.     else if ((c == '-') && (c1 == '>'))
  3821.       {
  3822.         nextchar = skip_white_space (getch ());
  3823.         if (nextchar == '(')
  3824.           {
  3825.         int next_c = skip_white_space (getch ());
  3826.         if (next_c == ')')
  3827.           {
  3828.             nextchar = -1;
  3829.             value = POINTSAT_LEFT_RIGHT;
  3830.             goto done;
  3831.           }
  3832.         put_back (next_c);
  3833.           }
  3834.         if (nextchar == '*')
  3835.           {
  3836.         nextchar = -1;
  3837.         value = POINTSAT_STAR;
  3838.           }
  3839.         else
  3840.           value = POINTSAT;
  3841.         goto done;
  3842.       }
  3843.     else if (c1 == '?' && (c == '<' || c == '>'))
  3844.       {
  3845.         token_buffer[3] = 0;
  3846.  
  3847.         c1 = getch ();
  3848.         yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
  3849.         if (c1 == '=')
  3850.           {
  3851.         /* <?= or >?= expression.  */
  3852.         token_buffer[2] = c1;
  3853.         value = ASSIGN;
  3854.           }
  3855.         else
  3856.           {
  3857.         value = MIN_MAX;
  3858.         nextchar = c1;
  3859.           }
  3860.         if (pedantic)
  3861.           error ("use of `operator %s' is not standard C++",
  3862.              token_buffer);
  3863.         goto done;
  3864.       }
  3865.  
  3866.     nextchar = c1;
  3867.     token_buffer[1] = 0;
  3868.  
  3869.     value = c;
  3870.     goto done;
  3871.       }
  3872.  
  3873.     case ':':
  3874.       c = getch ();
  3875.       if (c == ':')
  3876.     {
  3877.       token_buffer[1] = ':';
  3878.       token_buffer[2] = '\0';
  3879.       value = SCOPE;
  3880.       yylval.itype = 1;
  3881.     }
  3882.       else
  3883.     {
  3884.       nextchar = c;
  3885.       value = ':';
  3886.     }
  3887.       break;
  3888.  
  3889.     case 0:
  3890.       /* Don't make yyparse think this is eof.  */
  3891.       value = 1;
  3892.       break;
  3893.  
  3894.     case '(':
  3895.       /* try, weakly, to handle casts to pointers to functions.  */
  3896.       nextchar = skip_white_space (getch ());
  3897.       if (nextchar == '*')
  3898.     {
  3899.       int next_c = skip_white_space (getch ());
  3900.       if (next_c == ')')
  3901.         {
  3902.           nextchar = -1;
  3903.           yylval.ttype = build1 (INDIRECT_REF, 0, 0);
  3904.           value = PAREN_STAR_PAREN;
  3905.         }
  3906.       else
  3907.         {
  3908.           put_back (next_c);
  3909.           value = c;
  3910.         }
  3911.     }
  3912.       else if (nextchar == ')')
  3913.     {
  3914.       nextchar = -1;
  3915.       yylval.ttype = NULL_TREE;
  3916.       value = LEFT_RIGHT;
  3917.     }
  3918.       else value = c;
  3919.       break;
  3920.  
  3921.     default:
  3922.       value = c;
  3923.     }
  3924.  
  3925. done:
  3926. /*  yylloc.last_line = lineno; */
  3927. #ifdef GATHER_STATISTICS
  3928.   token_count[value] += 1;
  3929. #endif
  3930.  
  3931.   return value;
  3932. }
  3933.  
  3934. typedef enum
  3935. {
  3936.   d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
  3937.   id_kind, op_id_kind, perm_list_kind, temp_list_kind,
  3938.   vec_kind, x_kind, lang_decl, lang_type, all_kinds
  3939. } tree_node_kind;
  3940. extern int tree_node_counts[];
  3941. extern int tree_node_sizes[];
  3942. extern char *tree_node_kind_names[];
  3943.  
  3944. /* Place to save freed lang_decls which were allocated on the
  3945.    permanent_obstack.  @@ Not currently used.  */
  3946. tree free_lang_decl_chain;
  3947.  
  3948. tree
  3949. build_lang_decl (code, name, type)
  3950.      enum tree_code code;
  3951.      tree name;
  3952.      tree type;
  3953. {
  3954.   register tree t = build_decl (code, name, type);
  3955.   struct obstack *obstack = current_obstack;
  3956.   register int i = sizeof (struct lang_decl) / sizeof (int);
  3957.   register int *pi;
  3958.  
  3959.   if (! TREE_PERMANENT (t))
  3960.     obstack = saveable_obstack;
  3961.   else
  3962.     /* Could be that saveable is permanent and current is not.  */
  3963.     obstack = &permanent_obstack;
  3964.  
  3965.   if (free_lang_decl_chain && obstack == &permanent_obstack)
  3966.     {
  3967.       pi = (int *)free_lang_decl_chain;
  3968.       free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
  3969.     }
  3970.   else
  3971.     pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
  3972.  
  3973.   while (i > 0)
  3974.     pi[--i] = 0;
  3975.  
  3976.   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
  3977.   LANG_DECL_PERMANENT ((struct lang_decl *) pi)
  3978.     = obstack == &permanent_obstack;
  3979.   my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
  3980.       == TREE_PERMANENT  (t), 234);
  3981.   DECL_MAIN_VARIANT (t) = t;
  3982.   if (current_lang_name == lang_name_cplusplus)
  3983.     {
  3984.       DECL_LANGUAGE (t) = lang_cplusplus;
  3985. #ifndef NO_AUTO_OVERLOAD
  3986.       if (code == FUNCTION_DECL && name != 0
  3987.       && ! (IDENTIFIER_LENGTH (name) == 4
  3988.         && IDENTIFIER_POINTER (name)[0] == 'm'
  3989.         && strcmp (IDENTIFIER_POINTER (name), "main") == 0)
  3990.       && ! (IDENTIFIER_LENGTH (name) > 10
  3991.         && IDENTIFIER_POINTER (name)[0] == '_'
  3992.         && IDENTIFIER_POINTER (name)[1] == '_'
  3993.         && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
  3994.     TREE_OVERLOADED (name) = 1;
  3995. #endif
  3996.     }
  3997.   else if (current_lang_name == lang_name_c)
  3998.     DECL_LANGUAGE (t) = lang_c;
  3999.   else my_friendly_abort (64);
  4000.  
  4001. #if 0 /* not yet, should get fixed properly later */
  4002.   if (code == TYPE_DECL)
  4003.     {
  4004.       tree id;
  4005.       id = get_identifier (build_overload_name (type, 1, 1));
  4006.       DECL_ASSEMBLER_NAME (t) = id;
  4007.     }
  4008.  
  4009. #endif
  4010. #ifdef GATHER_STATISTICS
  4011.   tree_node_counts[(int)lang_decl] += 1;
  4012.   tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
  4013. #endif
  4014.  
  4015.   return t;
  4016. }
  4017.  
  4018. tree
  4019. build_lang_field_decl (code, name, type)
  4020.      enum tree_code code;
  4021.      tree name;
  4022.      tree type;
  4023. {
  4024.   extern struct obstack *current_obstack, *saveable_obstack;
  4025.   register tree t = build_decl (code, name, type);
  4026.   struct obstack *obstack = current_obstack;
  4027.   register int i = sizeof (struct lang_decl_flags) / sizeof (int);
  4028.   register int *pi;
  4029. #if 0 /* not yet, should get fixed properly later */
  4030.  
  4031.   if (code == TYPE_DECL)
  4032.     {
  4033.       tree id;
  4034.       id = get_identifier (build_overload_name (type, 1, 1));
  4035.       DECL_ASSEMBLER_NAME (t) = id;
  4036.     }
  4037. #endif
  4038.  
  4039.   if (! TREE_PERMANENT (t))
  4040.     obstack = saveable_obstack;
  4041.   else
  4042.     my_friendly_assert (obstack == &permanent_obstack, 235);
  4043.  
  4044.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
  4045.   while (i > 0)
  4046.     pi[--i] = 0;
  4047.  
  4048.   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
  4049.   return t;
  4050. }
  4051.  
  4052. void
  4053. copy_lang_decl (node)
  4054.      tree node;
  4055. {
  4056.   int size;
  4057.   int *pi;
  4058.  
  4059.   if (TREE_CODE (node) == FIELD_DECL)
  4060.     size = sizeof (struct lang_decl_flags);
  4061.   else
  4062.     size = sizeof (struct lang_decl);
  4063.   pi = (int *)obstack_alloc (&permanent_obstack, size);
  4064.   bcopy ((char *)DECL_LANG_SPECIFIC (node), (char *)pi, size);
  4065.   DECL_LANG_SPECIFIC (node) = (struct lang_decl *)pi;
  4066. }
  4067.  
  4068. tree
  4069. make_lang_type (code)
  4070.      enum tree_code code;
  4071. {
  4072.   extern struct obstack *current_obstack, *saveable_obstack;
  4073.   register tree t = make_node (code);
  4074.   struct obstack *obstack = current_obstack;
  4075.   register int i = sizeof (struct lang_type) / sizeof (int);
  4076.   register int *pi;
  4077.  
  4078.   /* Set up some flags that give proper default behavior.  */
  4079.   IS_AGGR_TYPE (t) = 1;
  4080.  
  4081.   if (! TREE_PERMANENT (t))
  4082.     obstack = saveable_obstack;
  4083.   else
  4084.     my_friendly_assert (obstack == &permanent_obstack, 236);
  4085.  
  4086.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
  4087.   while (i > 0)
  4088.     pi[--i] = 0;
  4089.  
  4090.   TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
  4091.   CLASSTYPE_AS_LIST (t) = build_tree_list (NULL_TREE, t);
  4092.   CLASSTYPE_INTERFACE_UNKNOWN (t) = interface_unknown;
  4093.   CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
  4094.   CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
  4095.   TYPE_BINFO (t) = make_binfo (integer_zero_node, t, 0, 0, 0);
  4096.   CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
  4097.  
  4098.   /* Make sure this is laid out, for ease of use later.
  4099.      In the presence of parse errors, the normal was of assuring
  4100.      this might not ever get executed, so we lay it out *immediately*.  */
  4101.   build_pointer_type (t);
  4102.  
  4103. #ifdef GATHER_STATISTICS
  4104.   tree_node_counts[(int)lang_type] += 1;
  4105.   tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
  4106. #endif
  4107.  
  4108.   return t;
  4109. }
  4110.  
  4111. void
  4112. copy_decl_lang_specific (decl)
  4113.      tree decl;
  4114. {
  4115.   extern struct obstack *current_obstack, *saveable_obstack;
  4116.   register int *old = (int *)DECL_LANG_SPECIFIC (decl);
  4117.   struct obstack *obstack = current_obstack;
  4118.   register int i = sizeof (struct lang_decl) / sizeof (int);
  4119.   register int *pi;
  4120.  
  4121.   if (! TREE_PERMANENT (decl))
  4122.     obstack = saveable_obstack;
  4123.   else
  4124.     my_friendly_assert (obstack == &permanent_obstack, 237);
  4125.  
  4126.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
  4127.   while (i-- > 0)
  4128.     pi[i] = old[i];
  4129.  
  4130.   DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi;
  4131.  
  4132. #ifdef GATHER_STATISTICS
  4133.   tree_node_counts[(int)lang_decl] += 1;
  4134.   tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
  4135. #endif
  4136. }
  4137.  
  4138. void
  4139. dump_time_statistics ()
  4140. {
  4141.   register tree prev = 0, decl, next;
  4142.   int this_time = my_get_run_time ();
  4143.   TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
  4144.     += this_time - body_time;
  4145.  
  4146.   fprintf (stderr, "\n******\n");
  4147.   print_time ("header files (total)", header_time);
  4148.   print_time ("main file (total)", this_time - body_time);
  4149.   fprintf (stderr, "ratio = %g : 1\n",
  4150.        (double)header_time / (double)(this_time - body_time));
  4151.   fprintf (stderr, "\n******\n");
  4152.  
  4153.   for (decl = filename_times; decl; decl = next)
  4154.     {
  4155.       next = IDENTIFIER_GLOBAL_VALUE (decl);
  4156.       IDENTIFIER_GLOBAL_VALUE (decl) = prev;
  4157.       prev = decl;
  4158.     }
  4159.  
  4160.   for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
  4161.     print_time (IDENTIFIER_POINTER (decl),
  4162.         TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
  4163. }
  4164.  
  4165. void
  4166. compiler_error (s, v, v2)
  4167.      char *s;
  4168.      int v, v2;            /* @@also used as pointer */
  4169. {
  4170.   char buf[1024];
  4171.   sprintf (buf, s, v, v2);
  4172.   error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
  4173. }
  4174.  
  4175. void
  4176. compiler_error_with_decl (decl, s)
  4177.      tree decl;
  4178.      char *s;
  4179. {
  4180.   char *name;
  4181.   count_error (0);
  4182.  
  4183.   report_error_function (0);
  4184.  
  4185.   if (TREE_CODE (decl) == PARM_DECL)
  4186.     fprintf (stderr, "%s:%d: ",
  4187.          DECL_SOURCE_FILE (DECL_CONTEXT (decl)),
  4188.          DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
  4189.   else
  4190.     fprintf (stderr, "%s:%d: ",
  4191.          DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
  4192.  
  4193.   name = lang_printable_name (decl);
  4194.   if (name)
  4195.     fprintf (stderr, s, name);
  4196.   else
  4197.     fprintf (stderr, s, "((anonymous))");
  4198.   fprintf (stderr, " (compiler error)\n");
  4199. }
  4200.  
  4201. void
  4202. yyerror (string)
  4203.      char *string;
  4204. {
  4205.   extern int end_of_file;
  4206.   extern int input_redirected ();
  4207.   char buf[200];
  4208.  
  4209.   strcpy (buf, string);
  4210.  
  4211.   /* We can't print string and character constants well
  4212.      because the token_buffer contains the result of processing escapes.  */
  4213.   if (end_of_file)
  4214.     strcat (buf, input_redirected ()
  4215.         ? " at end of saved text"
  4216.         : " at end of input");
  4217.   else if (token_buffer[0] == 0)
  4218.     strcat (buf, " at null character");
  4219.   else if (token_buffer[0] == '"')
  4220.     strcat (buf, " before string constant");
  4221.   else if (token_buffer[0] == '\'')
  4222.     strcat (buf, " before character constant");
  4223.   else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
  4224.     sprintf (buf + strlen (buf), " before character 0%o",
  4225.          (unsigned char) token_buffer[0]);
  4226.   else
  4227.     strcat (buf, " before `%s'");
  4228.  
  4229.   error (buf, token_buffer);
  4230. }
  4231.